Commit fc5b81d1f6df7342f0963120b2cf3e919d6fc08a

Authored by Mark McLoughlin
Committed by Anthony Liguori
1 parent df7a607b

net: set a default value for sndbuf=

On reflection, perhaps it does make sense to set a default value for
the sndbuf= tap parameter.

For best effect, sndbuf= should be set to just below the capacity of
the physical NIC.

Setting it higher will cause packets to be dropped before the limit
is hit. Setting it much lower will not cause any problems unless
you set it low enough such that the guest cannot queue up new packets
before the NIC has emptied its queue.

In Linux, txqueuelen=1000 by default for ethernet NICs. Given a 1500
byte MTU, 1Mb is a good choice for sndbuf.

If it turns out that txqueuelen is actually much lower than this, then
sndbuf is essentially disabled. In the event that txqueuelen is much
higher, it's unlikely that the NIC will be able to empty a 1Mb queue.

Thanks to Herbert Xu for this logic.

Signed-off-by: Mark McLoughlin <markmc@redhat.com>
Cc: Herbert Xu <herbert.xu@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Showing 2 changed files with 31 additions and 6 deletions
... ... @@ -1396,17 +1396,39 @@ static void tap_send(void *opaque)
1396 1396 } while (size > 0);
1397 1397 }
1398 1398  
1399   -static void tap_set_sndbuf(TAPState *s, int sndbuf, Monitor *mon)
1400   -{
1401 1399 #ifdef TUNSETSNDBUF
  1400 +/* sndbuf should be set to a value lower than the tx queue
  1401 + * capacity of any destination network interface.
  1402 + * Ethernet NICs generally have txqueuelen=1000, so 1Mb is
  1403 + * a good default, given a 1500 byte MTU.
  1404 + */
  1405 +#define TAP_DEFAULT_SNDBUF 1024*1024
  1406 +
  1407 +static void tap_set_sndbuf(TAPState *s, const char *sndbuf_str, Monitor *mon)
  1408 +{
  1409 + int sndbuf = TAP_DEFAULT_SNDBUF;
  1410 +
  1411 + if (sndbuf_str) {
  1412 + sndbuf = atoi(sndbuf_str);
  1413 + }
  1414 +
  1415 + if (!sndbuf) {
  1416 + sndbuf = INT_MAX;
  1417 + }
  1418 +
1402 1419 if (ioctl(s->fd, TUNSETSNDBUF, &sndbuf) == -1) {
1403 1420 config_error(mon, "TUNSETSNDBUF ioctl failed: %s\n",
1404 1421 strerror(errno));
1405 1422 }
  1423 +}
1406 1424 #else
1407   - config_error(mon, "No '-net tap,sndbuf=<nbytes>' support available\n");
1408   -#endif
  1425 +static void tap_set_sndbuf(TAPState *s, const char *sndbuf_str, Monitor *mon)
  1426 +{
  1427 + if (sndbuf_str) {
  1428 + config_error(mon, "No '-net tap,sndbuf=<nbytes>' support available\n");
  1429 + }
1409 1430 }
  1431 +#endif /* TUNSETSNDBUF */
1410 1432  
1411 1433 static void tap_cleanup(VLANClientState *vc)
1412 1434 {
... ... @@ -2654,9 +2676,11 @@ int net_client_init(Monitor *mon, const char *device, const char *p)
2654 2676 s = net_tap_init(vlan, device, name, ifname, setup_script, down_script);
2655 2677 }
2656 2678 if (s != NULL) {
  2679 + const char *sndbuf_str = NULL;
2657 2680 if (get_param_value(buf, sizeof(buf), "sndbuf", p)) {
2658   - tap_set_sndbuf(s, atoi(buf), mon);
  2681 + sndbuf_str = buf;
2659 2682 }
  2683 + tap_set_sndbuf(s, sndbuf_str, mon);
2660 2684 ret = 0;
2661 2685 } else {
2662 2686 ret = -1;
... ...
qemu-options.hx
... ... @@ -778,7 +778,8 @@ DEF(&quot;net&quot;, HAS_ARG, QEMU_OPTION_net,
778 778 " use '[down]script=no' to disable script execution;\n"
779 779 " use 'fd=h' to connect to an already opened TAP interface\n"
780 780 #ifdef TUNSETSNDBUF
781   - " use 'sndbuf=nbytes' to limit the size of the send buffer\n"
  781 + " use 'sndbuf=nbytes' to limit the size of the send buffer; the\n"
  782 + " default of 'sndbuf=1048576' can be disabled using 'sndbuf=0'\n"
782 783 #endif
783 784 #endif
784 785 "-net socket[,vlan=n][,name=str][,fd=h][,listen=[host]:port][,connect=host:port]\n"
... ...