[v2] examples/l3fwd: support setting the data size of mbuf

Message ID 20241018024253.4075609-1-chaoyong.he@corigine.com (mailing list archive)
State New
Delegated to: Thomas Monjalon
Headers
Series [v2] examples/l3fwd: support setting the data size of mbuf |

Checks

Context Check Description
ci/checkpatch success coding style OK
ci/loongarch-compilation success Compilation OK
ci/loongarch-unit-testing success Unit Testing PASS
ci/Intel-compilation success Compilation OK
ci/github-robot: build success github build: passed
ci/intel-Testing success Testing PASS
ci/intel-Functional success Functional PASS
ci/iol-intel-Functional success Functional Testing PASS
ci/iol-mellanox-Performance success Performance Testing PASS
ci/iol-unit-amd64-testing fail Testing issues
ci/iol-unit-arm64-testing fail Testing issues
ci/iol-compile-arm64-testing success Testing PASS
ci/iol-sample-apps-testing success Testing PASS
ci/iol-compile-amd64-testing success Testing PASS

Commit Message

Chaoyong He Oct. 18, 2024, 2:42 a.m. UTC
From: Long Wu <long.wu@corigine.com>

The previous code used a macro as the data size for mbuf
to create the mempool and users cannot modify the size.

Now modify the code to support setting the data size of
mbuf by '--mbuf-size' parameter. If user does not add the
parameter in start command line, the default size is still
'RTE_MBUF_DEFAULT_BUF_SIZE'.

Examples:
dpdk-l3fwd -l 0-3 -- -p 0x03 --mbuf-size=4096

Signed-off-by: Long Wu <long.wu@corigine.com>
Reviewed-by: Chaoyong He <chaoyong.he@corigine.com>
Acked-by: Morten Brørup <mb@smartsharesystems.com>

---
v2:
* Modify some logic following the advices of reviewer.
* Add the 'Acked-by' tag.
---
 doc/guides/sample_app_ug/l3_forward.rst |  2 ++
 examples/l3fwd/main.c                   | 31 ++++++++++++++++++++++---
 2 files changed, 30 insertions(+), 3 deletions(-)
  

Comments

lihuisong (C) Oct. 18, 2024, 2:50 a.m. UTC | #1
在 2024/10/18 10:42, Chaoyong He 写道:
> From: Long Wu <long.wu@corigine.com>
>
> The previous code used a macro as the data size for mbuf
> to create the mempool and users cannot modify the size.
>
> Now modify the code to support setting the data size of
> mbuf by '--mbuf-size' parameter. If user does not add the
> parameter in start command line, the default size is still
> 'RTE_MBUF_DEFAULT_BUF_SIZE'.
>
> Examples:
> dpdk-l3fwd -l 0-3 -- -p 0x03 --mbuf-size=4096
>
> Signed-off-by: Long Wu <long.wu@corigine.com>
> Reviewed-by: Chaoyong He <chaoyong.he@corigine.com>
> Acked-by: Morten Brørup <mb@smartsharesystems.com>
>

Acked-by: Huisong Li<lihuisong@huawei.com>
  
Stephen Hemminger Oct. 18, 2024, 2:59 a.m. UTC | #2
On Fri, 18 Oct 2024 10:42:53 +0800
Chaoyong He <chaoyong.he@corigine.com> wrote:

> From: Long Wu <long.wu@corigine.com>
> 
> The previous code used a macro as the data size for mbuf
> to create the mempool and users cannot modify the size.
> 
> Now modify the code to support setting the data size of
> mbuf by '--mbuf-size' parameter. If user does not add the
> parameter in start command line, the default size is still
> 'RTE_MBUF_DEFAULT_BUF_SIZE'.
> 
> Examples:
> dpdk-l3fwd -l 0-3 -- -p 0x03 --mbuf-size=4096
> 
> Signed-off-by: Long Wu <long.wu@corigine.com>
> Reviewed-by: Chaoyong He <chaoyong.he@corigine.com>
> Acked-by: Morten Brørup <mb@smartsharesystems.com>
> 
> ---
> v2:
> * Modify some logic following the advices of reviewer.
> * Add the 'Acked-by' tag.
> ---
>  doc/guides/sample_app_ug/l3_forward.rst |  2 ++
>  examples/l3fwd/main.c                   | 31 ++++++++++++++++++++++---
>  2 files changed, 30 insertions(+), 3 deletions(-)
> 
> diff --git a/doc/guides/sample_app_ug/l3_forward.rst b/doc/guides/sample_app_ug/l3_forward.rst
> index 1cc2c1dd1d..5afbbb242b 100644
> --- a/doc/guides/sample_app_ug/l3_forward.rst
> +++ b/doc/guides/sample_app_ug/l3_forward.rst
> @@ -143,6 +143,8 @@ Where,
>  * ``--alg=<val>:`` optional, ACL classify method to use, one of:
>    ``scalar|sse|avx2|neon|altivec|avx512x16|avx512x32``
>  
> +* ``--mbuf-size=N:`` Optional, Set the data size of mbuf to N bytes.
> +
>  * ``-E:`` Optional, enable exact match,
>    legacy flag, please use ``--lookup=em`` instead.
>  
> diff --git a/examples/l3fwd/main.c b/examples/l3fwd/main.c
> index 01b763e5ba..ed5d0c2608 100644
> --- a/examples/l3fwd/main.c
> +++ b/examples/l3fwd/main.c
> @@ -140,6 +140,7 @@ uint32_t max_pkt_len;
>  #ifdef RTE_LIB_EVENTDEV
>  static struct rte_mempool *vector_pool[RTE_MAX_ETHPORTS];
>  #endif
> +static uint16_t mbuf_data_size = RTE_MBUF_DEFAULT_DATAROOM;
>  static struct rte_mempool *pktmbuf_pool[RTE_MAX_ETHPORTS][NB_SOCKETS];
>  static uint8_t lkp_per_socket[NB_SOCKETS];
>  
> @@ -448,7 +449,8 @@ print_usage(const char *prgname)
>  		"                    One is ACL entry at while line leads with character '%c',\n"
>  		"                    another is route entry at while line leads with character '%c'.\n"
>  		"  --rule_ipv6=FILE: Specify the ipv6 rules entries file.\n"
> -		"  --alg: ACL classify method to use, one of: %s.\n\n",
> +		"  --alg: ACL classify method to use, one of: %s.\n"
> +		"  --mbuf-size=N: Set the data size of mbuf to N bytes.\n\n",
>  		prgname, RX_DESC_DEFAULT, TX_DESC_DEFAULT,
>  		ACL_LEAD_CHAR, ROUTE_LEAD_CHAR, alg);
>  }
> @@ -667,6 +669,22 @@ parse_lookup(const char *optarg)
>  	return 0;
>  }
>  
> +static void
> +parse_mbuf_data_size(const char *optarg)
> +{
> +	char *end = NULL;
> +
> +	mbuf_data_size = strtoul(optarg, &end, 10);
> +	if ((optarg[0] == '\0') || (end == NULL) || (*end != '\0'))
> +		rte_exit(EXIT_FAILURE, "Invalid mbuf data size: %s\n", optarg);
> +
> +	if (mbuf_data_size < RTE_ETHER_MIN_LEN ||
> +			mbuf_data_size > 0xFFFF - RTE_PKTMBUF_HEADROOM)

For clarity replace 0xffff with UINT16_MAX (which is data_len)

> +		rte_exit(EXIT_FAILURE,
> +				"mbuf-size should be >= %u and <= %u\n",
> +				RTE_ETHER_MIN_LEN, 0xFFFF - RTE_PKTMBUF_HEADROOM);
> +}
> +

Not sure why this is needed? What is the problem with the original code?
Are you trying to force packets to be segmented?
  
Chaoyong He Oct. 18, 2024, 3:21 a.m. UTC | #3
> On Fri, 18 Oct 2024 10:42:53 +0800
> Chaoyong He <chaoyong.he@corigine.com> wrote:
> 
> > From: Long Wu <long.wu@corigine.com>
> >
> > The previous code used a macro as the data size for mbuf to create the
> > mempool and users cannot modify the size.
> >
> > Now modify the code to support setting the data size of mbuf by
> > '--mbuf-size' parameter. If user does not add the parameter in start
> > command line, the default size is still 'RTE_MBUF_DEFAULT_BUF_SIZE'.
> >
> > Examples:
> > dpdk-l3fwd -l 0-3 -- -p 0x03 --mbuf-size=4096
> >
> > Signed-off-by: Long Wu <long.wu@corigine.com>
> > Reviewed-by: Chaoyong He <chaoyong.he@corigine.com>
> > Acked-by: Morten Brørup <mb@smartsharesystems.com>
> >
> > ---
> > v2:
> > * Modify some logic following the advices of reviewer.
> > * Add the 'Acked-by' tag.
> > ---
> >  doc/guides/sample_app_ug/l3_forward.rst |  2 ++
> >  examples/l3fwd/main.c                   | 31 ++++++++++++++++++++++---
> >  2 files changed, 30 insertions(+), 3 deletions(-)
> >
> > diff --git a/doc/guides/sample_app_ug/l3_forward.rst
> > b/doc/guides/sample_app_ug/l3_forward.rst
> > index 1cc2c1dd1d..5afbbb242b 100644
> > --- a/doc/guides/sample_app_ug/l3_forward.rst
> > +++ b/doc/guides/sample_app_ug/l3_forward.rst
> > @@ -143,6 +143,8 @@ Where,
> >  * ``--alg=<val>:`` optional, ACL classify method to use, one of:
> >    ``scalar|sse|avx2|neon|altivec|avx512x16|avx512x32``
> >
> > +* ``--mbuf-size=N:`` Optional, Set the data size of mbuf to N bytes.
> > +
> >  * ``-E:`` Optional, enable exact match,
> >    legacy flag, please use ``--lookup=em`` instead.
> >
> > diff --git a/examples/l3fwd/main.c b/examples/l3fwd/main.c index
> > 01b763e5ba..ed5d0c2608 100644
> > --- a/examples/l3fwd/main.c
> > +++ b/examples/l3fwd/main.c
> > @@ -140,6 +140,7 @@ uint32_t max_pkt_len;  #ifdef RTE_LIB_EVENTDEV
> > static struct rte_mempool *vector_pool[RTE_MAX_ETHPORTS];  #endif
> > +static uint16_t mbuf_data_size = RTE_MBUF_DEFAULT_DATAROOM;
> >  static struct rte_mempool
> > *pktmbuf_pool[RTE_MAX_ETHPORTS][NB_SOCKETS];
> >  static uint8_t lkp_per_socket[NB_SOCKETS];
> >
> > @@ -448,7 +449,8 @@ print_usage(const char *prgname)
> >  		"                    One is ACL entry at while line leads with character
> '%c',\n"
> >  		"                    another is route entry at while line leads with
> character '%c'.\n"
> >  		"  --rule_ipv6=FILE: Specify the ipv6 rules entries file.\n"
> > -		"  --alg: ACL classify method to use, one of: %s.\n\n",
> > +		"  --alg: ACL classify method to use, one of: %s.\n"
> > +		"  --mbuf-size=N: Set the data size of mbuf to N bytes.\n\n",
> >  		prgname, RX_DESC_DEFAULT, TX_DESC_DEFAULT,
> >  		ACL_LEAD_CHAR, ROUTE_LEAD_CHAR, alg);  } @@ -667,6
> +669,22 @@
> > parse_lookup(const char *optarg)
> >  	return 0;
> >  }
> >
> > +static void
> > +parse_mbuf_data_size(const char *optarg) {
> > +	char *end = NULL;
> > +
> > +	mbuf_data_size = strtoul(optarg, &end, 10);
> > +	if ((optarg[0] == '\0') || (end == NULL) || (*end != '\0'))
> > +		rte_exit(EXIT_FAILURE, "Invalid mbuf data size: %s\n",
> optarg);
> > +
> > +	if (mbuf_data_size < RTE_ETHER_MIN_LEN ||
> > +			mbuf_data_size > 0xFFFF -
> RTE_PKTMBUF_HEADROOM)
> 
> For clarity replace 0xffff with UINT16_MAX (which is data_len)
> 
> > +		rte_exit(EXIT_FAILURE,
> > +				"mbuf-size should be >= %u and <= %u\n",
> > +				RTE_ETHER_MIN_LEN, 0xFFFF -
> RTE_PKTMBUF_HEADROOM); }
> > +
> 
> Not sure why this is needed? What is the problem with the original code?
> Are you trying to force packets to be segmented?

Actually, we are trying to force packets *not* segmented by making the mbuf size large enough to hold the packets.

In our user case, we start l3fwd app with parameter '--max-pkt-len 4000', and obviously the original logic with RTE_MBUF_DEFAULT_DATAROOM mbuf size will cause the packets to be segmented.
Which is not what we want, so we add this new '--mbuf-size=4096' parameter, the mbuf size will large enough to hold even the largest packet.

Do you think this make sense?
  
Stephen Hemminger Oct. 18, 2024, 3:42 a.m. UTC | #4
On Fri, 18 Oct 2024 03:21:28 +0000
Chaoyong He <chaoyong.he@corigine.com> wrote:

> > RTE_PKTMBUF_HEADROOM); }  
> > > +  
> > 
> > Not sure why this is needed? What is the problem with the original code?
> > Are you trying to force packets to be segmented?  
> 
> Actually, we are trying to force packets *not* segmented by making the mbuf size large enough to hold the packets.
> 
> In our user case, we start l3fwd app with parameter '--max-pkt-len 4000', and obviously the original logic with RTE_MBUF_DEFAULT_DATAROOM mbuf size will cause the packets to be segmented.
> Which is not what we want, so we add this new '--mbuf-size=4096' parameter, the mbuf size will large enough to hold even the largest packet.
> 
> Do you think this make sense?

Maybe query the driver, and use the max_rx_pkt_len as input to deciding the right mbuf size.
If max-pkt-len was 4000 and driver can only take 2K buffers, then use 2K mbuf size.
If max-pkt-len was 1500 then use mtu + headroom and round up
  
Chaoyong He Oct. 18, 2024, 5:50 a.m. UTC | #5
> On Fri, 18 Oct 2024 03:21:28 +0000
> Chaoyong He <chaoyong.he@corigine.com> wrote:
> 
> > > RTE_PKTMBUF_HEADROOM); }
> > > > +
> > >
> > > Not sure why this is needed? What is the problem with the original code?
> > > Are you trying to force packets to be segmented?
> >
> > Actually, we are trying to force packets *not* segmented by making the
> mbuf size large enough to hold the packets.
> >
> > In our user case, we start l3fwd app with parameter '--max-pkt-len 4000',
> and obviously the original logic with RTE_MBUF_DEFAULT_DATAROOM mbuf
> size will cause the packets to be segmented.
> > Which is not what we want, so we add this new '--mbuf-size=4096'
> parameter, the mbuf size will large enough to hold even the largest packet.
> >
> > Do you think this make sense?
> 
> Maybe query the driver, and use the max_rx_pkt_len as input to deciding the
> right mbuf size.

Sorry, I am not quite understanding here.
I can't find 'max_rx_pkt_len' in l3fwd app, instead it's exist testpmd app.
Could you please explain a little more about the advice?

> If max-pkt-len was 4000 and driver can only take 2K buffers, then use 2K mbuf
> size.
> If max-pkt-len was 1500 then use mtu + headroom and round up
  
Stephen Hemminger Oct. 18, 2024, 3:59 p.m. UTC | #6
On Fri, 18 Oct 2024 05:50:20 +0000
Chaoyong He <chaoyong.he@corigine.com> wrote:

> > On Fri, 18 Oct 2024 03:21:28 +0000
> > Chaoyong He <chaoyong.he@corigine.com> wrote:
> >   
> > > > RTE_PKTMBUF_HEADROOM); }  
> > > > > +  
> > > >
> > > > Not sure why this is needed? What is the problem with the original code?
> > > > Are you trying to force packets to be segmented?  
> > >
> > > Actually, we are trying to force packets *not* segmented by making the  
> > mbuf size large enough to hold the packets.  
> > >
> > > In our user case, we start l3fwd app with parameter '--max-pkt-len 4000',  
> > and obviously the original logic with RTE_MBUF_DEFAULT_DATAROOM mbuf
> > size will cause the packets to be segmented.  
> > > Which is not what we want, so we add this new '--mbuf-size=4096'  
> > parameter, the mbuf size will large enough to hold even the largest packet.  
> > >
> > > Do you think this make sense?  
> > 
> > Maybe query the driver, and use the max_rx_pkt_len as input to deciding the
> > right mbuf size.  
> 
> Sorry, I am not quite understanding here.
> I can't find 'max_rx_pkt_len' in l3fwd app, instead it's exist testpmd app.
> Could you please explain a little more about the advice?

In rte_eth_dev_info, I meant the field max_rx_bufsize and there is also max_rx_pktlen.

> 
> > If max-pkt-len was 4000 and driver can only take 2K buffers, then use 2K mbuf
> > size.
> > If max-pkt-len was 1500 then use mtu + headroom and round up
  
Chaoyong He Oct. 21, 2024, 2 a.m. UTC | #7
> On Fri, 18 Oct 2024 05:50:20 +0000
> Chaoyong He <chaoyong.he@corigine.com> wrote:
> 
> > > On Fri, 18 Oct 2024 03:21:28 +0000
> > > Chaoyong He <chaoyong.he@corigine.com> wrote:
> > >
> > > > > RTE_PKTMBUF_HEADROOM); }
> > > > > > +
> > > > >
> > > > > Not sure why this is needed? What is the problem with the original
> code?
> > > > > Are you trying to force packets to be segmented?
> > > >
> > > > Actually, we are trying to force packets *not* segmented by making
> > > > the
> > > mbuf size large enough to hold the packets.
> > > >
> > > > In our user case, we start l3fwd app with parameter '--max-pkt-len
> > > > 4000',
> > > and obviously the original logic with RTE_MBUF_DEFAULT_DATAROOM
> mbuf
> > > size will cause the packets to be segmented.
> > > > Which is not what we want, so we add this new '--mbuf-size=4096'
> > > parameter, the mbuf size will large enough to hold even the largest packet.
> > > >
> > > > Do you think this make sense?
> > >
> > > Maybe query the driver, and use the max_rx_pkt_len as input to
> > > deciding the right mbuf size.
> >
> > Sorry, I am not quite understanding here.
> > I can't find 'max_rx_pkt_len' in l3fwd app, instead it's exist testpmd app.
> > Could you please explain a little more about the advice?
> 
> In rte_eth_dev_info, I meant the field max_rx_bufsize and there is also
> max_rx_pktlen.
> 
> >
> > > If max-pkt-len was 4000 and driver can only take 2K buffers, then
> > > use 2K mbuf size.
> > > If max-pkt-len was 1500 then use mtu + headroom and round up

Oh, I understand what you mean now, thanks for the clarification.
But the solution you suppose is not flexible enough, thus can't satisfy our needs.

Follow your example and consider this situation:
If max-pkt-len was 4000 and driver can only take 2K buffers, then
use 2K mbuf size.

But we want to measure the performance when the mbuf size is 1024 and 512.

Then there is no way to do this in your solution, I suppose?

But with our '--mbuf-size' parameter, we can easily do that.
Thanks for your hint, we realized our solution also has a little problem, which not 
consider the 'max_rx_bufsize' of rte_eth_dev_info, and we will fix that in the next version patch.
  
Stephen Hemminger Oct. 21, 2024, 5:07 p.m. UTC | #8
On Mon, 21 Oct 2024 02:00:55 +0000
Chaoyong He <chaoyong.he@corigine.com> wrote:

> > On Fri, 18 Oct 2024 05:50:20 +0000
> > Chaoyong He <chaoyong.he@corigine.com> wrote:
> >   
> > > > On Fri, 18 Oct 2024 03:21:28 +0000
> > > > Chaoyong He <chaoyong.he@corigine.com> wrote:
> > > >  
> > > > > > RTE_PKTMBUF_HEADROOM); }  
> > > > > > > +  
> > > > > >
> > > > > > Not sure why this is needed? What is the problem with the original  
> > code?  
> > > > > > Are you trying to force packets to be segmented?  
> > > > >
> > > > > Actually, we are trying to force packets *not* segmented by making
> > > > > the  
> > > > mbuf size large enough to hold the packets.  
> > > > >
> > > > > In our user case, we start l3fwd app with parameter '--max-pkt-len
> > > > > 4000',  
> > > > and obviously the original logic with RTE_MBUF_DEFAULT_DATAROOM  
> > mbuf  
> > > > size will cause the packets to be segmented.  
> > > > > Which is not what we want, so we add this new '--mbuf-size=4096'  
> > > > parameter, the mbuf size will large enough to hold even the largest packet.  
> > > > >
> > > > > Do you think this make sense?  
> > > >
> > > > Maybe query the driver, and use the max_rx_pkt_len as input to
> > > > deciding the right mbuf size.  
> > >
> > > Sorry, I am not quite understanding here.
> > > I can't find 'max_rx_pkt_len' in l3fwd app, instead it's exist testpmd app.
> > > Could you please explain a little more about the advice?  
> > 
> > In rte_eth_dev_info, I meant the field max_rx_bufsize and there is also
> > max_rx_pktlen.
> >   
> > >  
> > > > If max-pkt-len was 4000 and driver can only take 2K buffers, then
> > > > use 2K mbuf size.
> > > > If max-pkt-len was 1500 then use mtu + headroom and round up  
> 
> Oh, I understand what you mean now, thanks for the clarification.
> But the solution you suppose is not flexible enough, thus can't satisfy our needs.
> 
> Follow your example and consider this situation:
> If max-pkt-len was 4000 and driver can only take 2K buffers, then
> use 2K mbuf size.
> 
> But we want to measure the performance when the mbuf size is 1024 and 512.
> 
> Then there is no way to do this in your solution, I suppose?
> 
> But with our '--mbuf-size' parameter, we can easily do that.
> Thanks for your hint, we realized our solution also has a little problem, which not 
> consider the 'max_rx_bufsize' of rte_eth_dev_info, and we will fix that in the next version patch.

It would be best if the default was to choose mbuf size automatically,
but since this is a test program having an override is also useful.

In general l3fwd is target at usability (less options) and test-pmd is focused on testing (lots of options).
There is a tradeoff here. l3fwd should not get as complex as test-pmd or there is no point.
  

Patch

diff --git a/doc/guides/sample_app_ug/l3_forward.rst b/doc/guides/sample_app_ug/l3_forward.rst
index 1cc2c1dd1d..5afbbb242b 100644
--- a/doc/guides/sample_app_ug/l3_forward.rst
+++ b/doc/guides/sample_app_ug/l3_forward.rst
@@ -143,6 +143,8 @@  Where,
 * ``--alg=<val>:`` optional, ACL classify method to use, one of:
   ``scalar|sse|avx2|neon|altivec|avx512x16|avx512x32``
 
+* ``--mbuf-size=N:`` Optional, Set the data size of mbuf to N bytes.
+
 * ``-E:`` Optional, enable exact match,
   legacy flag, please use ``--lookup=em`` instead.
 
diff --git a/examples/l3fwd/main.c b/examples/l3fwd/main.c
index 01b763e5ba..ed5d0c2608 100644
--- a/examples/l3fwd/main.c
+++ b/examples/l3fwd/main.c
@@ -140,6 +140,7 @@  uint32_t max_pkt_len;
 #ifdef RTE_LIB_EVENTDEV
 static struct rte_mempool *vector_pool[RTE_MAX_ETHPORTS];
 #endif
+static uint16_t mbuf_data_size = RTE_MBUF_DEFAULT_DATAROOM;
 static struct rte_mempool *pktmbuf_pool[RTE_MAX_ETHPORTS][NB_SOCKETS];
 static uint8_t lkp_per_socket[NB_SOCKETS];
 
@@ -448,7 +449,8 @@  print_usage(const char *prgname)
 		"                    One is ACL entry at while line leads with character '%c',\n"
 		"                    another is route entry at while line leads with character '%c'.\n"
 		"  --rule_ipv6=FILE: Specify the ipv6 rules entries file.\n"
-		"  --alg: ACL classify method to use, one of: %s.\n\n",
+		"  --alg: ACL classify method to use, one of: %s.\n"
+		"  --mbuf-size=N: Set the data size of mbuf to N bytes.\n\n",
 		prgname, RX_DESC_DEFAULT, TX_DESC_DEFAULT,
 		ACL_LEAD_CHAR, ROUTE_LEAD_CHAR, alg);
 }
@@ -667,6 +669,22 @@  parse_lookup(const char *optarg)
 	return 0;
 }
 
+static void
+parse_mbuf_data_size(const char *optarg)
+{
+	char *end = NULL;
+
+	mbuf_data_size = strtoul(optarg, &end, 10);
+	if ((optarg[0] == '\0') || (end == NULL) || (*end != '\0'))
+		rte_exit(EXIT_FAILURE, "Invalid mbuf data size: %s\n", optarg);
+
+	if (mbuf_data_size < RTE_ETHER_MIN_LEN ||
+			mbuf_data_size > 0xFFFF - RTE_PKTMBUF_HEADROOM)
+		rte_exit(EXIT_FAILURE,
+				"mbuf-size should be >= %u and <= %u\n",
+				RTE_ETHER_MIN_LEN, 0xFFFF - RTE_PKTMBUF_HEADROOM);
+}
+
 #define MAX_JUMBO_PKT_LEN  9600
 
 static const char short_options[] =
@@ -698,6 +716,7 @@  static const char short_options[] =
 #define CMD_LINE_OPT_RULE_IPV4 "rule_ipv4"
 #define CMD_LINE_OPT_RULE_IPV6 "rule_ipv6"
 #define CMD_LINE_OPT_ALG "alg"
+#define CMD_LINE_OPT_MBUF_SIZE "mbuf-size"
 
 enum {
 	/* long options mapped to a short option */
@@ -726,7 +745,8 @@  enum {
 	CMD_LINE_OPT_LOOKUP_NUM,
 	CMD_LINE_OPT_ENABLE_VECTOR_NUM,
 	CMD_LINE_OPT_VECTOR_SIZE_NUM,
-	CMD_LINE_OPT_VECTOR_TMO_NS_NUM
+	CMD_LINE_OPT_VECTOR_TMO_NS_NUM,
+	CMD_LINE_OPT_MBUF_SIZE_NUM,
 };
 
 static const struct option lgopts[] = {
@@ -753,6 +773,7 @@  static const struct option lgopts[] = {
 	{CMD_LINE_OPT_RULE_IPV4,   1, 0, CMD_LINE_OPT_RULE_IPV4_NUM},
 	{CMD_LINE_OPT_RULE_IPV6,   1, 0, CMD_LINE_OPT_RULE_IPV6_NUM},
 	{CMD_LINE_OPT_ALG,   1, 0, CMD_LINE_OPT_ALG_NUM},
+	{CMD_LINE_OPT_MBUF_SIZE, 1, 0, CMD_LINE_OPT_MBUF_SIZE_NUM},
 	{NULL, 0, 0, 0}
 };
 
@@ -934,6 +955,9 @@  parse_args(int argc, char **argv)
 		case CMD_LINE_OPT_ALG_NUM:
 			l3fwd_set_alg(optarg);
 			break;
+		case CMD_LINE_OPT_MBUF_SIZE_NUM:
+			parse_mbuf_data_size(optarg);
+			break;
 		default:
 			print_usage(prgname);
 			return -1;
@@ -1034,7 +1058,8 @@  init_mem(uint16_t portid, unsigned int nb_mbuf)
 			pktmbuf_pool[portid][socketid] =
 				rte_pktmbuf_pool_create(s, nb_mbuf,
 					MEMPOOL_CACHE_SIZE, 0,
-					RTE_MBUF_DEFAULT_BUF_SIZE, socketid);
+					mbuf_data_size + RTE_PKTMBUF_HEADROOM,
+					socketid);
 			if (pktmbuf_pool[portid][socketid] == NULL)
 				rte_exit(EXIT_FAILURE,
 					"Cannot init mbuf pool on socket %d\n",