From 1fa9dbea57d2dbc5d9b728a83a583c3a8f675410 Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Sun, 23 May 2010 07:43:04 +0200 Subject: [PATCH 1/1] dccp_send: send data in MPS-sized chunks As mandated by RFC 4340, 14., DCCP maintains an internal variable called 'Maximum Packet Size', which can be queried via the DCCP_SOCKOPT_GET_CUR_MPS socket option. This option has been available since 2007-10-04 (v2.6.23) and is documented in Documentation/networking/dccp.txt. The Maximum Packet Size takes into account the path MTU, size of headers and the estimated overhead for DCCP options. The following table shows various values that were determined experimentally between two hosts: +----------+------------+--------------+--------------------+ | Medium | IP version | MTU in bytes | Resulting DCCP MPS | +----------+------------+--------------+--------------------+ | Ethernet | IPv4 | 1500 | 1424 bytes | | Ethernet | IPv6 | 1500 | 1404 bytes | +----------+------------+--------------+--------------------+ | WiFi | IPv4 | 576 | 500 bytes | | WiFi | IPv4 | 1280 | 1204 bytes | | WiFi | IPv4 | 1500 | 1424 bytes | | WiFi (a) | IPv4 | 2048 | 1972 bytes | +----------+------------+--------------+--------------------+ | WiFi | IPv6 | 576 | see (b) | | WiFi | IPv6 | 1280 | 1184 bytes | | WiFi | IPv6 | 1500 | 1404 bytes | | WiFi (a) | IPv6 | 2048 | 1952 bytes | +----------+------------+--------------+--------------------+ Notes: (a) WiFi normally uses Ethernet MTU of 1500 bytes, but the medium supports a much larger MTU (Fragmentation threshold) of up to about 2300 bytes (system used 802.11g). (b) 576 byte MTU not tested for IPv6 since IPv6 mandates a minimum MTU of 1280 bytes, as per RFC 2460 section 5 (also RFC 5405, 3.2). The patch implements the dccp init_fec() function based on the DCCP MPS. --- dccp_send.c | 25 +++++++++++++++++++------ net.h | 8 +++++++- 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/dccp_send.c b/dccp_send.c index 0657d11c..77bee097 100644 --- a/dccp_send.c +++ b/dccp_send.c @@ -32,9 +32,6 @@ #include "server.cmdline.h" #include "acl.h" -/** Do not write more than that many bytes at once. */ -#define DCCP_MAX_BYTES_PER_WRITE 1024 - static struct sender_status dccp_sender_status, *dss = &dccp_sender_status; struct dccp_fec_client { @@ -86,9 +83,26 @@ static void dccp_shutdown_clients(void) dccp_shutdown_client(sc); } +/** * Obtain current MPS according to RFC 4340, sec. 14. */ +static int dccp_init_fec(struct sender_client *sc) +{ + int mps, ret; + socklen_t ml = sizeof(mps); + + /* If call fails, return some sensible minimum value */ + ret = getsockopt(sc->fd, SOL_DCCP, DCCP_SOCKOPT_GET_CUR_MPS, &mps, &ml); + if (ret < 0) { + PARA_NOTICE_LOG("can not determine MPS: %s\n", strerror(errno)); + mps = generic_max_transport_msg_size(sc->fd) - DCCP_MAX_HEADER; + } + PARA_INFO_LOG("current MPS = %d bytes\n", mps); + assert(mps > 0); + return mps; +} + static int dccp_send_fec(struct sender_client *sc, char *buf, size_t len) { - int ret = write_nonblock(sc->fd, buf, len, DCCP_MAX_BYTES_PER_WRITE); + int ret = write_nonblock(sc->fd, buf, len, 0); if (ret < 0) dccp_shutdown_client(sc); @@ -127,8 +141,7 @@ static void dccp_post_select(fd_set *rfds, __a_unused fd_set *wfds) sc->private_data = dfc; dfc->fcp.slices_per_group = 4; dfc->fcp.data_slices_per_group = 3; - dfc->fcp.max_slice_bytes = DCCP_MAX_BYTES_PER_WRITE; /* FIXME */ - dfc->fcp.init_fec = NULL; /* FIXME */ + dfc->fcp.init_fec = dccp_init_fec; dfc->fcp.send_fec = dccp_send_fec; dfc->fc = vss_add_fec_client(sc, &dfc->fcp); } diff --git a/net.h b/net.h index db610318..9da63ba1 100644 --- a/net.h +++ b/net.h @@ -36,6 +36,10 @@ #define SOL_DCCP 269 /**< Linux socket level. */ #endif +#ifndef DCCP_SOCKOPT_GET_CUR_MPS +#define DCCP_SOCKOPT_GET_CUR_MPS 5 /**< Max packet size, RFC 4340, 14. */ +#endif + #ifndef DCCP_SOCKOPT_AVAILABLE_CCIDS #define DCCP_SOCKOPT_AVAILABLE_CCIDS 12 /**< List of supported CCIDs. */ #endif @@ -154,6 +158,8 @@ ssize_t send_cred_buffer(int, char*); /** * Functions and definitions to support \p IPPROTO_DCCP */ -/** Hardcoded maximum number of separate CCID modules compiled into a host */ +/** Estimated worst-case length of a DCCP header including options. */ +#define DCCP_MAX_HEADER 128 +/** Hardcoded maximum number of separate CCID modules compiled into a host. */ #define DCCP_MAX_HOST_CCIDS 20 extern int dccp_available_ccids(uint8_t **ccid_array); -- 2.39.2