summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmake/config/ipcp/broadcast.cmake3
-rw-r--r--cmake/config/ipcp/local.cmake30
-rw-r--r--cmake/config/ipcp/udp.cmake4
-rw-r--r--cmake/config/ipcp/unicast.cmake2
-rw-r--r--include/ouroboros/flow.h3
-rw-r--r--include/ouroboros/ipcp-dev.h4
-rw-r--r--src/ipcpd/broadcast/dt.c2
-rw-r--r--src/ipcpd/broadcast/main.c2
-rw-r--r--src/ipcpd/config.h.in6
-rw-r--r--src/ipcpd/eth/eth.c6
-rw-r--r--src/ipcpd/ipcp.c3
-rw-r--r--src/ipcpd/ipcp.h1
-rw-r--r--src/ipcpd/local/main.c9
-rw-r--r--src/ipcpd/udp/udp.c57
-rw-r--r--src/ipcpd/unicast/fa.c6
-rw-r--r--src/irmd/main.c4
-rw-r--r--src/irmd/reg/flow.c2
-rw-r--r--src/irmd/reg/tests/flow_test.c16
-rw-r--r--src/irmd/reg/tests/reg_test.c19
-rw-r--r--src/lib/pb/model.proto1
-rw-r--r--src/lib/protobuf.c2
21 files changed, 169 insertions, 13 deletions
diff --git a/cmake/config/ipcp/broadcast.cmake b/cmake/config/ipcp/broadcast.cmake
index 79f41d10..f521ed8e 100644
--- a/cmake/config/ipcp/broadcast.cmake
+++ b/cmake/config/ipcp/broadcast.cmake
@@ -4,3 +4,6 @@ set(IPCP_BROADCAST_TARGET ipcpd-broadcast)
set(IPCP_BROADCAST_MPL 100 CACHE STRING
"Default maximum packet lifetime for the Broadcast IPCP, in ms")
+
+set(IPCP_BROADCAST_MTU 1400 CACHE STRING
+ "Layer MTU advertised by the Broadcast IPCP, in bytes")
diff --git a/cmake/config/ipcp/local.cmake b/cmake/config/ipcp/local.cmake
index 88ee8998..60ff23ee 100644
--- a/cmake/config/ipcp/local.cmake
+++ b/cmake/config/ipcp/local.cmake
@@ -5,5 +5,35 @@ set(IPCP_LOCAL_TARGET ipcpd-local)
set(IPCP_LOCAL_MPL 100 CACHE STRING
"Default maximum packet lifetime for the Local IPCP, in ms")
+set(IPCP_LOCAL_MTU 65000 CACHE STRING
+ "Layer MTU advertised by the Local IPCP, in bytes")
+
set(IPCP_LOCAL_POLLING FALSE CACHE BOOL
"Enable active polling in the Local IPCP for low-latency mode")
+
+# IPCP_LOCAL_MTU must fit in the largest enabled GSPP and PUP class
+# (sender-side allocation: daemons use GSPP, apps use PUP). Reserve a
+# margin for sizeof(struct ssm_pk_buff) + HEADSPACE + TAILSPACE.
+math(EXPR _ssm_pk_overhead
+ "${SSM_PK_BUFF_HEADSPACE} + ${SSM_PK_BUFF_TAILSPACE} + 64")
+
+foreach(_pool GSPP PUP)
+ set(_largest 0)
+ foreach(_pair "256;256" "512;512" "1K;1024" "2K;2048" "4K;4096"
+ "16K;16384" "64K;65536" "256K;262144" "1M;1048576")
+ list(GET _pair 0 _name)
+ list(GET _pair 1 _bytes)
+ if(SSM_${_pool}_${_name}_BLOCKS GREATER 0
+ AND _bytes GREATER _largest)
+ set(_largest ${_bytes})
+ endif()
+ endforeach()
+ math(EXPR _avail "${_largest} - ${_ssm_pk_overhead}")
+ if(IPCP_LOCAL_MTU GREATER _avail)
+ message(FATAL_ERROR
+ "IPCP_LOCAL_MTU (${IPCP_LOCAL_MTU}) exceeds largest enabled "
+ "SSM_${_pool} class minus per-block overhead "
+ "(${_largest} - ${_ssm_pk_overhead} = ${_avail} bytes). "
+ "Lower IPCP_LOCAL_MTU or enable a larger SSM_${_pool}_*_BLOCKS.")
+ endif()
+endforeach()
diff --git a/cmake/config/ipcp/udp.cmake b/cmake/config/ipcp/udp.cmake
index 0124c261..af84a844 100644
--- a/cmake/config/ipcp/udp.cmake
+++ b/cmake/config/ipcp/udp.cmake
@@ -10,3 +10,7 @@ set(IPCP_UDP_WR_THR 3 CACHE STRING
"Number of writer threads in UDP IPCPs")
set(IPCP_UDP_MPL 5000 CACHE STRING
"Default maximum packet lifetime for the UDP IPCPs, in ms")
+set(IPCP_UDP4_MTU 1472 CACHE STRING
+ "Fallback UDP4 layer MTU when getsockopt(IP_MTU) is unavailable, in bytes")
+set(IPCP_UDP6_MTU 1452 CACHE STRING
+ "Fallback UDP6 layer MTU when getsockopt(IPV6_MTU) is unavailable, in bytes")
diff --git a/cmake/config/ipcp/unicast.cmake b/cmake/config/ipcp/unicast.cmake
index 3b5b0ce7..b8d4d516 100644
--- a/cmake/config/ipcp/unicast.cmake
+++ b/cmake/config/ipcp/unicast.cmake
@@ -4,6 +4,8 @@ set(IPCP_UNICAST_TARGET ipcpd-unicast)
set(IPCP_UNICAST_MPL 100 CACHE STRING
"Default maximum packet lifetime for the Unicast IPCP, in ms")
+set(IPCP_UNICAST_MTU 1400 CACHE STRING
+ "Layer MTU advertised by the Unicast IPCP, in bytes (TODO: derive per-flow from n-1 path MTU minus DT PCI)")
set(PFT_SIZE 256 CACHE STRING
"Prefix forwarding table size for the Unicast IPCP")
diff --git a/include/ouroboros/flow.h b/include/ouroboros/flow.h
index fe4582e7..8b096410 100644
--- a/include/ouroboros/flow.h
+++ b/include/ouroboros/flow.h
@@ -25,6 +25,7 @@
#include <ouroboros/qos.h>
+#include <stdint.h>
#include <sys/types.h>
#define SYMMKEYSZ 32
@@ -50,6 +51,8 @@ struct flow_info {
time_t mpl;
+ uint32_t mtu; /* n-1 layer MTU in bytes, 0 = unknown */
+
struct qos_spec qs;
enum flow_state state;
diff --git a/include/ouroboros/ipcp-dev.h b/include/ouroboros/ipcp-dev.h
index 93236271..d23f757e 100644
--- a/include/ouroboros/ipcp-dev.h
+++ b/include/ouroboros/ipcp-dev.h
@@ -28,16 +28,20 @@
#include <ouroboros/ssm_pool.h>
#include <ouroboros/utils.h>
+#include <stdint.h>
+
int ipcp_create_r(const struct ipcp_info * info);
int ipcp_flow_req_arr(const buffer_t * dst,
qosspec_t qs,
time_t mpl,
+ uint32_t mtu,
const buffer_t * data);
int ipcp_flow_alloc_reply(int fd,
int response,
time_t mpl,
+ uint32_t mtu,
const buffer_t * data);
int ipcp_flow_read(int fd,
diff --git a/src/ipcpd/broadcast/dt.c b/src/ipcpd/broadcast/dt.c
index 30e89a4f..95483e33 100644
--- a/src/ipcpd/broadcast/dt.c
+++ b/src/ipcpd/broadcast/dt.c
@@ -28,7 +28,7 @@
#include "config.h"
-#define BROADCAST_MTU 1400 /* FIXME: avoid packet copy. */
+#define BROADCAST_MTU IPCP_BROADCAST_MTU /* FIXME: avoid packet copy. */
#define DT "dt"
#define OUROBOROS_PREFIX DT
diff --git a/src/ipcpd/broadcast/main.c b/src/ipcpd/broadcast/main.c
index b3cbdc79..77e22531 100644
--- a/src/ipcpd/broadcast/main.c
+++ b/src/ipcpd/broadcast/main.c
@@ -242,7 +242,7 @@ static int broadcast_ipcp_join(int fd,
notifier_event(NOTIFY_DT_CONN_ADD, &conn);
- ipcp_flow_alloc_reply(fd, 0, mpl, &data);
+ ipcp_flow_alloc_reply(fd, 0, mpl, IPCP_BROADCAST_MTU, &data);
return 0;
}
diff --git a/src/ipcpd/config.h.in b/src/ipcpd/config.h.in
index 37ee2c5e..a719fa3b 100644
--- a/src/ipcpd/config.h.in
+++ b/src/ipcpd/config.h.in
@@ -46,6 +46,7 @@
#define IPCP_SCHED_THR_MUL @IPCP_SCHED_THR_MUL@
#define PFT_SIZE @PFT_SIZE@
#define IPCP_UNICAST_MPL @IPCP_UNICAST_MPL@
+#define IPCP_UNICAST_MTU @IPCP_UNICAST_MTU@
#define CONNMGR_RCV_TIMEOUT @CONNMGR_RCV_TIMEOUT@
#cmakedefine DISABLE_CORE_LOCK
@@ -66,6 +67,8 @@
#define IPCP_UDP_RD_THR @IPCP_UDP_RD_THR@
#define IPCP_UDP_WR_THR @IPCP_UDP_WR_THR@
#define IPCP_UDP_MPL @IPCP_UDP_MPL@
+#define IPCP_UDP4_MTU @IPCP_UDP4_MTU@
+#define IPCP_UDP6_MTU @IPCP_UDP6_MTU@
/* eth */
#cmakedefine HAVE_NETMAP
@@ -80,7 +83,8 @@
/* local */
#define IPCP_LOCAL_MPL @IPCP_LOCAL_MPL@
+#define IPCP_LOCAL_MTU @IPCP_LOCAL_MTU@
/* broadcast */
-/* local */
#define IPCP_BROADCAST_MPL @IPCP_BROADCAST_MPL@
+#define IPCP_BROADCAST_MTU @IPCP_BROADCAST_MTU@
diff --git a/src/ipcpd/eth/eth.c b/src/ipcpd/eth/eth.c
index 10a8b338..1dc2b8fe 100644
--- a/src/ipcpd/eth/eth.c
+++ b/src/ipcpd/eth/eth.c
@@ -841,7 +841,8 @@ static int eth_ipcp_req(uint8_t * r_addr,
{
int fd;
- fd = ipcp_wait_flow_req_arr(dst, qs, IPCP_ETH_MPL, data);
+ fd = ipcp_wait_flow_req_arr(dst, qs, IPCP_ETH_MPL,
+ ETH_MAX_PACKET_SIZE, data);
if (fd < 0) {
log_err("Could not get new flow from IRMd.");
return -1;
@@ -913,7 +914,8 @@ static int eth_ipcp_alloc_reply(uint8_t * r_addr,
#elif defined(BUILD_ETH_LLC)
log_dbg("Flow reply, fd %d, SSAP %d, DSAP %d.", fd, ssap, dsap);
#endif
- if ((ret = ipcp_flow_alloc_reply(fd, response, mpl, data)) < 0) {
+ if ((ret = ipcp_flow_alloc_reply(fd, response, mpl,
+ ETH_MAX_PACKET_SIZE, data)) < 0) {
log_err("Failed to reply to flow allocation.");
return -1;
}
diff --git a/src/ipcpd/ipcp.c b/src/ipcpd/ipcp.c
index 5ad2401f..1052a686 100644
--- a/src/ipcpd/ipcp.c
+++ b/src/ipcpd/ipcp.c
@@ -363,6 +363,7 @@ static void * acceptloop(void * o)
int ipcp_wait_flow_req_arr(const uint8_t * dst,
qosspec_t qs,
time_t mpl,
+ uint32_t mtu,
const buffer_t * data)
{
struct timespec ts = TIMESPEC_INIT_MS(ALLOC_TIMEOUT);
@@ -392,7 +393,7 @@ int ipcp_wait_flow_req_arr(const uint8_t * dst,
assert(ipcpd.alloc_id == -1);
- fd = ipcp_flow_req_arr(&hash, qs, mpl, data);
+ fd = ipcp_flow_req_arr(&hash, qs, mpl, mtu, data);
if (fd < 0) {
pthread_mutex_unlock(&ipcpd.alloc_lock);
log_err("Failed to get fd for flow.");
diff --git a/src/ipcpd/ipcp.h b/src/ipcpd/ipcp.h
index 26a780a3..0adcc694 100644
--- a/src/ipcpd/ipcp.h
+++ b/src/ipcpd/ipcp.h
@@ -98,6 +98,7 @@ enum ipcp_state ipcp_get_state(void);
int ipcp_wait_flow_req_arr(const uint8_t * dst,
qosspec_t qs,
time_t mpl,
+ uint32_t mtu,
const buffer_t * data);
int ipcp_wait_flow_resp(const int fd);
diff --git a/src/ipcpd/local/main.c b/src/ipcpd/local/main.c
index 2c867317..eb9836f2 100644
--- a/src/ipcpd/local/main.c
+++ b/src/ipcpd/local/main.c
@@ -203,7 +203,8 @@ static int local_ipcp_flow_alloc(int fd,
HASH_VAL32(dst), fd);
assert(dst);
- out_fd = ipcp_wait_flow_req_arr(dst, qs, IPCP_LOCAL_MPL, data);
+ out_fd = ipcp_wait_flow_req_arr(dst, qs, IPCP_LOCAL_MPL,
+ IPCP_LOCAL_MTU, data);
if (out_fd < 0) {
log_dbg("Flow allocation failed: %d", out_fd);
return -1;
@@ -255,14 +256,16 @@ static int local_ipcp_flow_alloc_resp(int fd,
}
if (response < 0) {
- ipcp_flow_alloc_reply(out_fd, response, mpl, data);
+ ipcp_flow_alloc_reply(out_fd, response, mpl,
+ IPCP_LOCAL_MTU, data);
log_info("Flow allocation rejected, fds (%d, %d).", out_fd, fd);
return 0;
}
fset_add(local_data.flows, fd);
- if (ipcp_flow_alloc_reply(out_fd, response, mpl, data) < 0) {
+ if (ipcp_flow_alloc_reply(out_fd, response, mpl,
+ IPCP_LOCAL_MTU, data) < 0) {
log_err("Failed to reply to allocation");
fset_del(local_data.flows, fd);
return -1;
diff --git a/src/ipcpd/udp/udp.c b/src/ipcpd/udp/udp.c
index 168ea718..8fba5a77 100644
--- a/src/ipcpd/udp/udp.c
+++ b/src/ipcpd/udp/udp.c
@@ -47,6 +47,10 @@
#include <stdlib.h>
#include <sys/wait.h>
#include <fcntl.h>
+#include <unistd.h>
+#if defined(__linux__)
+#include <netinet/ip.h>
+#endif
#define FLOW_REQ 1
#define FLOW_REPLY 2
@@ -130,6 +134,53 @@ static const char * __inet_ntop(const struct __ADDR * addr,
return inet_ntop(__AF, addr, buf, __ADDRSTRLEN);
}
+#if defined(BUILD_IPCP_UDP4)
+#define UDP_MTU_FALLBACK IPCP_UDP4_MTU
+#define UDP_IP_OVERHEAD 28U /* IPv4 + UDP */
+#else
+#define UDP_MTU_FALLBACK IPCP_UDP6_MTU
+#define UDP_IP_OVERHEAD 48U /* IPv6 + UDP */
+#endif
+
+static uint32_t udp_query_mtu(const struct __SOCKADDR * saddr)
+{
+#if defined(__linux__) && (defined(IP_MTU) || defined(IPV6_MTU))
+ int sock;
+ int mtu = 0;
+ socklen_t len = sizeof(mtu);
+
+ sock = socket(__AF, SOCK_DGRAM, IPPROTO_UDP);
+ if (sock < 0)
+ return UDP_MTU_FALLBACK;
+
+ if (connect(sock, (const struct sockaddr *) saddr,
+ sizeof(*saddr)) < 0)
+ goto fallback;
+
+#if defined(BUILD_IPCP_UDP4) && defined(IP_MTU)
+ if (getsockopt(sock, IPPROTO_IP, IP_MTU, &mtu, &len) < 0)
+ goto fallback;
+#elif defined(BUILD_IPCP_UDP6) && defined(IPV6_MTU)
+ if (getsockopt(sock, IPPROTO_IPV6, IPV6_MTU, &mtu, &len) < 0)
+ goto fallback;
+#else
+ goto fallback;
+#endif
+ close(sock);
+
+ if (mtu <= (int) UDP_IP_OVERHEAD)
+ return UDP_MTU_FALLBACK;
+
+ return (uint32_t) mtu - UDP_IP_OVERHEAD;
+
+ fallback:
+ close(sock);
+#else
+ (void) saddr;
+#endif
+ return UDP_MTU_FALLBACK;
+}
+
static int udp_data_init(void)
{
int i;
@@ -285,7 +336,8 @@ static int udp_ipcp_port_req(struct __SOCKADDR * c_saddr,
{
int fd;
- fd = ipcp_wait_flow_req_arr(dst, qs, IPCP_UDP_MPL, data);
+ fd = ipcp_wait_flow_req_arr(dst, qs, IPCP_UDP_MPL,
+ udp_query_mtu(c_saddr), data);
if (fd < 0) {
log_err("Could not get new flow from IRMd.");
return -1;
@@ -332,7 +384,8 @@ static int udp_ipcp_port_alloc_reply(const struct __SOCKADDR * saddr,
pthread_rwlock_unlock(&udp_data.flows_lock);
- if (ipcp_flow_alloc_reply(s_eid, response, mpl, data) < 0) {
+ if (ipcp_flow_alloc_reply(s_eid, response, mpl,
+ udp_query_mtu(saddr), data) < 0) {
log_err("Failed to reply to flow allocation.");
return -1;
}
diff --git a/src/ipcpd/unicast/fa.c b/src/ipcpd/unicast/fa.c
index 39928ab2..ca27108e 100644
--- a/src/ipcpd/unicast/fa.c
+++ b/src/ipcpd/unicast/fa.c
@@ -500,7 +500,8 @@ static int fa_handle_flow_req(struct fa_msg * msg,
qs.max_gap = ntoh32(msg->max_gap);
qs.timeout = ntoh32(msg->timeout);
- fd = ipcp_wait_flow_req_arr(dst, qs, IPCP_UNICAST_MPL, &data);
+ fd = ipcp_wait_flow_req_arr(dst, qs, IPCP_UNICAST_MPL,
+ IPCP_UNICAST_MTU, &data);
if (fd < 0)
return fd;
@@ -559,7 +560,8 @@ static int fa_handle_flow_reply(struct fa_msg * msg,
pthread_rwlock_unlock(&fa.flows_lock);
- if (ipcp_flow_alloc_reply(fd, response, mpl, &data) < 0) {
+ if (ipcp_flow_alloc_reply(fd, response, mpl,
+ IPCP_UNICAST_MTU, &data) < 0) {
log_err("Failed to reply for flow allocation on fd %d.", fd);
return -EIRMD;
}
diff --git a/src/irmd/main.c b/src/irmd/main.c
index 5a6245e0..ffb07334 100644
--- a/src/irmd/main.c
+++ b/src/irmd/main.c
@@ -87,6 +87,8 @@
#define OAP_SEEN_TIMER 20 /* s */
#define DEALLOC_TIME 300 /* s */
#define DIRECT_MPL 1 /* s */
+/* bytes; in-process, bounded only by PUP/GSPP. */
+#define DIRECT_MTU 65000
enum irm_state {
IRMD_NULL = 0,
@@ -1216,6 +1218,7 @@ static int flow_alloc_direct(const char * dst,
acc.n_1_pid = flow->n_pid;
acc.mpl = DIRECT_MPL;
+ acc.mtu = DIRECT_MTU;
acc.qs = flow->qs;
acc.state = FLOW_ALLOCATED;
@@ -1251,6 +1254,7 @@ static int flow_alloc_direct(const char * dst,
flow->id = acc.id;
flow->n_1_pid = acc.n_pid;
flow->mpl = DIRECT_MPL;
+ flow->mtu = DIRECT_MTU;
flow->state = FLOW_ALLOCATED;
log_info("Flow %d allocated (direct) for %d to %s.",
diff --git a/src/irmd/reg/flow.c b/src/irmd/reg/flow.c
index 93c3e128..5c709dea 100644
--- a/src/irmd/reg/flow.c
+++ b/src/irmd/reg/flow.c
@@ -42,6 +42,7 @@ struct reg_flow * reg_flow_create(const struct flow_info * info)
assert(info->n_pid != 0);
assert(info->n_1_pid == 0);
assert(info->mpl == 0);
+ assert(info->mtu == 0);
assert(info->state == FLOW_INIT);
flow = malloc(sizeof(*flow));
@@ -160,6 +161,7 @@ int reg_flow_update(struct reg_flow * flow,
assert(info->mpl != 0);
flow->info.mpl = info->mpl;
+ flow->info.mtu = info->mtu;
if (flow->info.state == FLOW_ALLOC_PENDING)
break;
diff --git a/src/irmd/reg/tests/flow_test.c b/src/irmd/reg/tests/flow_test.c
index 7e1c1360..10cd9f3d 100644
--- a/src/irmd/reg/tests/flow_test.c
+++ b/src/irmd/reg/tests/flow_test.c
@@ -122,6 +122,21 @@ static int test_reg_flow_create_has_mpl(void) {
return TEST_RC_SUCCESS;
}
+static int test_reg_flow_create_has_mtu(void) {
+ struct flow_info info = {
+ .id = 1,
+ .n_pid = 1,
+ .n_1_pid = 0,
+ .mtu = 1400,
+ .qs = qos_raw,
+ .state = FLOW_ALLOC_PENDING
+ };
+
+ reg_flow_create(&info); /* assert fail */
+
+ return TEST_RC_SUCCESS;
+}
+
static int test_reg_flow_update(void)
{
struct reg_flow * f;
@@ -210,6 +225,7 @@ static int test_reg_flow_assert_fails(void)
ret |= test_assert_fail(test_reg_flow_create_has_n_1_pid);
ret |= test_assert_fail(test_reg_flow_create_wrong_state);
ret |= test_assert_fail(test_reg_flow_create_has_mpl);
+ ret |= test_assert_fail(test_reg_flow_create_has_mtu);
ret |= test_assert_fail(test_reg_flow_update_wrong_id);
return ret;
diff --git a/src/irmd/reg/tests/reg_test.c b/src/irmd/reg/tests/reg_test.c
index 5a5178c2..dcc26783 100644
--- a/src/irmd/reg/tests/reg_test.c
+++ b/src/irmd/reg/tests/reg_test.c
@@ -31,6 +31,7 @@
#define TEST_N_1_PID 3999
#define TEST_FAKE_ID 9128349
#define TEST_MPL 5
+#define TEST_MTU 1400
#define TEST_PROG "reg_test" /* own binary for binary check */
#define TEST_IPCP "testipcp"
#define TEST_NAME "testname"
@@ -266,6 +267,7 @@ static int test_reg_accept_flow_success(void)
n_1_info.id = info.id;
n_1_info.mpl = 1;
+ n_1_info.mtu = TEST_MTU;
pthread_create(&thr, NULL, test_flow_respond_accept, &n_1_info);
@@ -284,6 +286,11 @@ static int test_reg_accept_flow_success(void)
goto fail;
}
+ if (info.mtu != TEST_MTU) {
+ printf("MTU not propagated.\n");
+ goto fail;
+ }
+
if (rbuf.data == NULL) {
printf("rbuf data not returned.\n");
goto fail;
@@ -363,6 +370,7 @@ static int test_reg_accept_flow_success_no_crypt(void)
n_1_info.id = info.id;
n_1_info.mpl = 1;
+ n_1_info.mtu = TEST_MTU;
pthread_create(&thr, NULL, test_flow_respond_accept, &n_1_info);
@@ -381,6 +389,11 @@ static int test_reg_accept_flow_success_no_crypt(void)
goto fail;
}
+ if (info.mtu != TEST_MTU) {
+ printf("MTU not propagated.\n");
+ goto fail;
+ }
+
if (rbuf.data == NULL) {
printf("rbuf data was not returned.\n");
goto fail;
@@ -533,6 +546,7 @@ static int test_reg_respond_alloc_duplicate(void)
n_1_info.id = info.id;
n_1_info.mpl = 1;
+ n_1_info.mtu = TEST_MTU;
pthread_create(&thr, NULL, test_flow_respond_alloc, &n_1_info);
@@ -547,6 +561,11 @@ static int test_reg_respond_alloc_duplicate(void)
pthread_join(thr, NULL);
freebuf(rbuf);
+ if (info.mtu != TEST_MTU) {
+ printf("MTU not propagated.\n");
+ goto fail;
+ }
+
/* Duplicate reply on an already-ALLOCATED flow must not assert. */
dup_info = n_1_info;
dup_info.state = FLOW_DEALLOCATED;
diff --git a/src/lib/pb/model.proto b/src/lib/pb/model.proto
index f1382f3d..51bea760 100644
--- a/src/lib/pb/model.proto
+++ b/src/lib/pb/model.proto
@@ -41,6 +41,7 @@ message flow_info_msg {
required uint32 state = 5;
required qosspec_msg qos = 6;
required uint32 uid = 7;
+ required uint32 mtu = 8; /* Layer MTU (bytes). */
}
message name_info_msg {
diff --git a/src/lib/protobuf.c b/src/lib/protobuf.c
index 28b3aab2..75c71dfd 100644
--- a/src/lib/protobuf.c
+++ b/src/lib/protobuf.c
@@ -81,6 +81,7 @@ flow_info_msg_t * flow_info_s_to_msg(const struct flow_info * s)
msg->mpl = s->mpl;
msg->state = s->state;
msg->uid = s->uid;
+ msg->mtu = s->mtu;
msg->qos = qos_spec_s_to_msg(&s->qs);
if (msg->qos == NULL)
goto fail_msg;
@@ -107,6 +108,7 @@ struct flow_info flow_info_msg_to_s(const flow_info_msg_t * msg)
s.mpl = msg->mpl;
s.state = msg->state;
s.uid = msg->uid;
+ s.mtu = msg->mtu;
s.qs = qos_spec_msg_to_s(msg->qos);
return s;