diff options
| -rw-r--r-- | cmake/config/ipcp/broadcast.cmake | 3 | ||||
| -rw-r--r-- | cmake/config/ipcp/local.cmake | 30 | ||||
| -rw-r--r-- | cmake/config/ipcp/udp.cmake | 4 | ||||
| -rw-r--r-- | cmake/config/ipcp/unicast.cmake | 2 | ||||
| -rw-r--r-- | include/ouroboros/flow.h | 3 | ||||
| -rw-r--r-- | include/ouroboros/ipcp-dev.h | 4 | ||||
| -rw-r--r-- | src/ipcpd/broadcast/dt.c | 2 | ||||
| -rw-r--r-- | src/ipcpd/broadcast/main.c | 2 | ||||
| -rw-r--r-- | src/ipcpd/config.h.in | 6 | ||||
| -rw-r--r-- | src/ipcpd/eth/eth.c | 6 | ||||
| -rw-r--r-- | src/ipcpd/ipcp.c | 3 | ||||
| -rw-r--r-- | src/ipcpd/ipcp.h | 1 | ||||
| -rw-r--r-- | src/ipcpd/local/main.c | 9 | ||||
| -rw-r--r-- | src/ipcpd/udp/udp.c | 57 | ||||
| -rw-r--r-- | src/ipcpd/unicast/fa.c | 6 | ||||
| -rw-r--r-- | src/irmd/main.c | 4 | ||||
| -rw-r--r-- | src/irmd/reg/flow.c | 2 | ||||
| -rw-r--r-- | src/irmd/reg/tests/flow_test.c | 16 | ||||
| -rw-r--r-- | src/irmd/reg/tests/reg_test.c | 19 | ||||
| -rw-r--r-- | src/lib/pb/model.proto | 1 | ||||
| -rw-r--r-- | src/lib/protobuf.c | 2 |
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; |
