summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/vcl/vppcom.c1
-rw-r--r--src/vnet/session/application_interface.h7
-rw-r--r--src/vnet/udp/udp.c29
-rw-r--r--src/vnet/udp/udp.h2
-rw-r--r--src/vnet/udp/udp_input.c10
5 files changed, 45 insertions, 4 deletions
diff --git a/src/vcl/vppcom.c b/src/vcl/vppcom.c
index dd37460a322..1591b0850a0 100644
--- a/src/vcl/vppcom.c
+++ b/src/vcl/vppcom.c
@@ -2012,7 +2012,6 @@ vcl_fifo_is_writeable (svm_fifo_t * f, u32 len, u8 is_dgram)
return max_enq >= (sizeof (session_dgram_hdr_t) + len);
else
return max_enq > 0;
-
}
always_inline int
diff --git a/src/vnet/session/application_interface.h b/src/vnet/session/application_interface.h
index b410c638155..d09432d0b52 100644
--- a/src/vnet/session/application_interface.h
+++ b/src/vnet/session/application_interface.h
@@ -694,8 +694,13 @@ app_recv_dgram_raw (svm_fifo_t * f, u8 * buf, u32 len,
svm_fifo_peek (f, 0, sizeof (ph), (u8 *) & ph);
ASSERT (ph.data_length >= ph.data_offset);
- svm_fifo_peek (f, sizeof (ph), sizeof (*at), (u8 *) at);
+ /* Check if we have the full dgram */
+ if (max_deq < (ph.data_length + SESSION_CONN_HDR_LEN)
+ && len >= ph.data_length)
+ return 0;
+
+ svm_fifo_peek (f, sizeof (ph), sizeof (*at), (u8 *) at);
len = clib_min (len, ph.data_length - ph.data_offset);
rv = svm_fifo_peek (f, ph.data_offset + SESSION_CONN_HDR_LEN, len, buf);
if (peek)
diff --git a/src/vnet/udp/udp.c b/src/vnet/udp/udp.c
index 48d518a984e..daab453f43d 100644
--- a/src/vnet/udp/udp.c
+++ b/src/vnet/udp/udp.c
@@ -196,6 +196,7 @@ udp_session_bind (u32 session_index, transport_endpoint_t * lcl)
listener->c_proto = TRANSPORT_PROTO_UDP;
listener->c_s_index = session_index;
listener->c_fib_index = lcl->fib_index;
+ listener->mss = um->default_mtu - sizeof (udp_header_t);
listener->flags |= UDP_CONN_F_OWNS_PORT | UDP_CONN_F_LISTEN;
lcl_ext = (transport_endpoint_cfg_t *) lcl;
if (lcl_ext->transport_flags & TRANSPORT_CFG_F_CONNECTED)
@@ -409,10 +410,14 @@ static int
udp_session_send_params (transport_connection_t * tconn,
transport_send_params_t * sp)
{
+ udp_connection_t *uc;
+
+ uc = udp_get_connection_from_transport (tconn);
+
/* No constraint on TX window */
sp->snd_space = ~0;
/* TODO figure out MTU of output interface */
- sp->snd_mss = 1460;
+ sp->snd_mss = uc->mss;
sp->tx_offset = 0;
sp->flags = 0;
return 0;
@@ -423,6 +428,7 @@ udp_open_connection (transport_endpoint_cfg_t * rmt)
{
vlib_main_t *vm = vlib_get_main ();
u32 thread_index = vm->thread_index;
+ udp_main_t *um = &udp_main;
ip46_address_t lcl_addr;
udp_connection_t *uc;
u16 lcl_port;
@@ -483,6 +489,7 @@ conn_alloc:
uc->c_is_ip4 = rmt->is_ip4;
uc->c_proto = TRANSPORT_PROTO_UDP;
uc->c_fib_index = rmt->fib_index;
+ uc->mss = rmt->mss ? rmt->mss : (um->default_mtu - sizeof (udp_header_t));
uc->flags |= UDP_CONN_F_OWNS_PORT;
if (rmt->transport_flags & TRANSPORT_CFG_F_CONNECTED)
uc->flags |= UDP_CONN_F_CONNECTED;
@@ -639,6 +646,8 @@ udp_init (vlib_main_t * vm)
vlib_node_add_next (vm, udp4_local_node.index, udp4_input_node.index);
um->local_to_input_edge[UDP_IP6] =
vlib_node_add_next (vm, udp6_local_node.index, udp6_input_node.index);
+
+ um->default_mtu = 1500;
return 0;
}
@@ -650,6 +659,24 @@ VLIB_INIT_FUNCTION (udp_init) =
};
/* *INDENT-ON* */
+static clib_error_t *
+udp_config_fn (vlib_main_t * vm, unformat_input_t * input)
+{
+ udp_main_t *um = &udp_main;
+ u32 tmp;
+
+ while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat (input, "mtu %u", &tmp))
+ um->default_mtu = tmp;
+ else
+ return clib_error_return (0, "unknown input `%U'",
+ format_unformat_error, input);
+ }
+ return 0;
+}
+
+VLIB_CONFIG_FUNCTION (udp_config_fn, "udp");
static clib_error_t *
show_udp_punt_fn (vlib_main_t * vm, unformat_input_t * input,
diff --git a/src/vnet/udp/udp.h b/src/vnet/udp/udp.h
index 9e1aad6fbe5..f7985c928c2 100644
--- a/src/vnet/udp/udp.h
+++ b/src/vnet/udp/udp.h
@@ -63,6 +63,7 @@ typedef struct
transport_connection_t connection; /**< must be first */
clib_spinlock_t rx_lock; /**< rx fifo lock */
u8 flags; /**< connection flags */
+ u16 mss; /**< connection mss */
} udp_connection_t;
#define foreach_udp4_dst_port \
@@ -171,6 +172,7 @@ typedef struct
clib_spinlock_t *peekers_write_locks;
udp_connection_t *listener_pool;
+ u16 default_mtu;
} udp_main_t;
extern udp_main_t udp_main;
diff --git a/src/vnet/udp/udp_input.c b/src/vnet/udp/udp_input.c
index 4b22cbef54d..1e1c60b419f 100644
--- a/src/vnet/udp/udp_input.c
+++ b/src/vnet/udp/udp_input.c
@@ -208,6 +208,7 @@ udp46_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
child0->c_rmt_port = udp0->src_port;
child0->c_is_ip4 = is_ip4;
child0->c_fib_index = tc0->fib_index;
+ child0->mss = uc0->mss;
child0->flags |= UDP_CONN_F_CONNECTED;
if (session_stream_accept (&child0->connection,
@@ -238,7 +239,14 @@ udp46_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
error0 = UDP_ERROR_FIFO_FULL;
goto trace0;
}
- hdr0.data_length = b0->current_length = data_len;
+
+ hdr0.data_length = data_len;
+ if (PREDICT_TRUE (!(b0->flags & VLIB_BUFFER_NEXT_PRESENT)))
+ b0->current_length = data_len;
+ else
+ b0->total_length_not_including_first_buffer = data_len
+ - b0->current_length;
+
hdr0.data_offset = 0;
ip_set (&hdr0.lcl_ip, lcl_addr, is_ip4);
ip_set (&hdr0.rmt_ip, rmt_addr, is_ip4);