title: How to increase UDP socket recv buffer size to its maximum for Linux program?
body: <p>I am trying to increase the receive buffer size for an UDP socket but the final size does not seem to be predictable :</p>
  <pre><code>    LOG_INFO(&quot;UDP echo server default receive buffer size : &quot; &lt;&lt; rcv_buf &lt;&lt; &quot; bytes&quot;);
  
      // increase default buffer sizes
      rcv_buf *= 3;
  
      LOG_INFO(&quot;trying to increase receive buffer size to : &quot; &lt;&lt; rcv_buf &lt;&lt; &quot; bytes&quot;);
  
      if (!SockWrap::set_recv_buf_size(m_handle, sizeof(m_sockaddr_in), rcv_buf))
          LOG_ERR(&quot;unable to set new receive buffer size&quot;);
  
      // checking the new size after possible modifications if any
      rcv_buf = SockWrap::recv_buf(m_handle, sizeof(m_sockaddr_in));
  
      if (rcv_buf == -1) {
          LOG_ERR(&quot;unable to read UDP echo server receive buffer size after modification&quot;);
      } else {
          LOG_INFO(&quot;UDP echo server new receive buffer size : &quot; &lt;&lt; rcv_buf &lt;&lt; &quot; bytes&quot;);
      }
  </code></pre>
  <p>Wrappers functions are :</p>
  <pre><code>bool SockWrap::set_recv_buf_size(int fd, socklen_t len, int size)
  {
      // SO_RCVBUF option is an integer
      int n = setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &amp;size, len);
  
      if (n == -1) {
  
          LOG_ERR(&quot;setsockopt : &quot; &lt;&lt; strerror(errno));
          return false;
      }
      return true;
  }
  </code></pre>
  <p>and</p>
  <pre><code>int SockWrap::recv_buf(int fd, socklen_t len)
  {
      // SO_RCVBUF option is an integer
      int optval;
  
      if (getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &amp;optval, &amp;len) == -1) {
  
          LOG_ERR(&quot;getsockopt : &quot; &lt;&lt; strerror(errno));
          return -1;
  
      } else
          return optval;
  }
  </code></pre>
  <p>output :</p>
  <pre><code>UDP echo server default receive buffer size : 212992 bytes
  trying to increase receive buffer size to : 638976 bytes
  UDP echo server new receive buffer size : 425984 bytes
  </code></pre>
  <p>I have check the limits of my system in <code>/proc/sys/net/ipv4</code>:</p>
  <pre><code>cat udp_rmem_min
  4096
  cat udp_mem
  186162  248216  372324
  </code></pre>
  <p>and in <code>/proc/sys/net/core</code></p>
  <pre><code>cat rmem_max
  212992
  cat rmem_default
  212992
  </code></pre>
  <p>So the first output seems pretty clear, the default recv buffer value is 212992 bytes which is defined by <code>rmem_default</code>.</p>
  <p>But then size is increased and suprisingly greater than <code>rmem_max</code> but still not what i wanted.</p>
  <p>Where this final value (425984 bytes) comes from ?</p>
  <p>Is this value a maximum and does it depends on how much memory is currently used by the kernel ?</p>
  <p><strong>EDIT :</strong></p>
  <p>Following the answer, i have tested other values and it's seems even possible to set <code>rmem_default</code> to be greater than <code>rmem_max</code> :</p>
  <pre><code>echo 500000 &gt; /proc/sys/net/core/rmem_default
  cat /proc/sys/net/core/rmem_default
  500000
  </code></pre>
  <p>Now before <code>setsockopt</code> is called, <code>getsockopt</code> returns (as always) <code>rmem_default</code>, not <code>rmem_default * 2</code> which is 500000.</p>
  <p>But if i use <code>setsockopt</code> to set the value to 500000 then <code>getsocktop</code> returns <code>rmem_max * 2</code> which is 425984.</p>
  <p>So it's seems that using <code>/proc</code> interface allows more control on the buffer size than <code>setsockopt</code>.</p>
  <p>What is the purpose of <code>rmem_max</code> if <code>rmem_default</code> can be greater ?</p>
  <pre><code>/* from kernel 5.10.63 net/core/sock.c */
  case SO_RCVBUF:
      /* Don't error on this BSD doesn't and if you think
       * about it this is right. Otherwise apps have to
       * play 'guess the biggest size' games. RCVBUF/SNDBUF
       * are treated in BSD as hints
       */
      __sock_set_rcvbuf(sk, min_t(u32, val, sysctl_rmem_max));
      break;
  </code></pre>
  <p>and</p>
  <pre><code>static void __sock_set_rcvbuf(struct sock *sk, int val)
  {
         /* Ensure val * 2 fits into an int, to prevent max_t() from treating it
          * as a negative value.
          */
          val = min_t(int, val, INT_MAX / 2);
          sk-&gt;sk_userlocks |= SOCK_RCVBUF_LOCK;
          /* We double it on the way in to account for &quot;struct sk_buff&quot; etc.
           * overhead.   Applications assume that the SO_RCVBUF setting they make
           * will allow that much actual data to be received on that socket.
           *
           * Applications are unaware that &quot;struct sk_buff&quot; and other overheads
           * allocate from the receive buffer during socket buffer allocation.
           *
           * And after considering the possible alternatives, returning the value
           * we actually used in getsockopt is the most desirable behavior.
           */
          WRITE_ONCE(sk-&gt;sk_rcvbuf, max_t(int, val * 2, SOCK_MIN_RCVBUF));
  }
  </code></pre>
  <p>But maybe this edit should be another (related) question.</p>
  <p>Thank you.</p>