+void
+tcp_update_rcv_wnd (tcp_connection_t * tc)
+{
+ i32 observed_wnd;
+ u32 available_space, max_fifo, wnd;
+
+ /*
+ * Figure out how much space we have available
+ */
+ available_space = stream_session_max_rx_enqueue (&tc->connection);
+ max_fifo = stream_session_fifo_size (&tc->connection);
+
+ ASSERT (tc->opt.mss < max_fifo);
+
+ if (available_space < tc->opt.mss && available_space < max_fifo / 8)
+ available_space = 0;
+
+ /*
+ * Use the above and what we know about what we've previously advertised
+ * to compute the new window
+ */
+ observed_wnd = (i32) tc->rcv_wnd - (tc->rcv_nxt - tc->rcv_las);
+ if (observed_wnd < 0)
+ observed_wnd = 0;
+
+ /* Bad. Thou shalt not shrink */
+ if (available_space < observed_wnd)
+ {
+ /* Does happen! */
+ wnd = observed_wnd;
+ }
+ else
+ {
+ wnd = available_space;
+ }
+
+ if (wnd && ((wnd << tc->rcv_wscale) >> tc->rcv_wscale != wnd))
+ wnd += 1 << tc->rcv_wscale;
+
+ tc->rcv_wnd = clib_min (wnd, TCP_WND_MAX << tc->rcv_wscale);