diff options
author | Akihiro Suda <akihiro.suda.cz@hco.ntt.co.jp> | 2019-07-10 15:07:37 +0900 |
---|---|---|
committer | Marc-André Lureau <marcandre.lureau@redhat.com> | 2019-08-01 10:57:57 +0400 |
commit | 09d410adbff5422b7ba7596bce0ca71f9f807ea9 (patch) | |
tree | 65e4ad7ec659bdb091acd65382f58851d7cdd9de /src | |
parent | ac916a56bedf449e481c4dc1cda192ca386ff939 (diff) | |
download | slirp-09d410adbff5422b7ba7596bce0ca71f9f807ea9.zip slirp-09d410adbff5422b7ba7596bce0ca71f9f807ea9.tar.gz slirp-09d410adbff5422b7ba7596bce0ca71f9f807ea9.tar.bz2 |
allow custom MTU
From https://github.com/rootless-containers/slirp4netns/blob/4889f5299f407d7d7566c76a3b8b5f71c99b6db5/qemu_patches/0002-slirp-allow-custom-MTU.patch
Original commits:
* https://github.com/rootless-containers/slirp4netns/commit/ea630a7e945cf538184ff1b1b4bd7b8ddc01993e
* https://github.com/rootless-containers/slirp4netns/commit/1508a66c93c223555f08651592dde3d2d708b166
* https://github.com/rootless-containers/slirp4netns/commit/19f3f41df4066d6103e6f882500e24db7ea7d9e1
* https://github.com/rootless-containers/slirp4netns/commit/a11abedafcc627ef0657999e63b211b0f26d4c02
* https://github.com/rootless-containers/slirp4netns/commit/2adbd7c449944d3b837164c86eedd3dcabbba1a6
Signed-off-by: Akihiro Suda <akihiro.suda.cz@hco.ntt.co.jp>
Diffstat (limited to 'src')
-rw-r--r-- | src/dhcpv6.c | 2 | ||||
-rw-r--r-- | src/if.h | 8 | ||||
-rw-r--r-- | src/ip6_icmp.c | 6 | ||||
-rw-r--r-- | src/ip6_input.c | 2 | ||||
-rw-r--r-- | src/ip_output.c | 4 | ||||
-rw-r--r-- | src/libslirp.h | 4 | ||||
-rw-r--r-- | src/mbuf.c | 8 | ||||
-rw-r--r-- | src/slirp.c | 8 | ||||
-rw-r--r-- | src/slirp.h | 3 | ||||
-rw-r--r-- | src/tcp.h | 18 | ||||
-rw-r--r-- | src/tcp_input.c | 8 | ||||
-rw-r--r-- | src/tcp_subr.c | 8 |
12 files changed, 46 insertions, 33 deletions
diff --git a/src/dhcpv6.c b/src/dhcpv6.c index bc041d5..ce5f203 100644 --- a/src/dhcpv6.c +++ b/src/dhcpv6.c @@ -178,7 +178,7 @@ static void dhcpv6_info_request(Slirp *slirp, struct sockaddr_in6 *srcsas, *resp++ = OPTION_BOOTFILE_URL >> 8; /* option-code high byte */ *resp++ = OPTION_BOOTFILE_URL; /* option-code low byte */ - smaxlen = (uint8_t *)m->m_data + IF_MTU - (resp + 2); + smaxlen = (uint8_t *)m->m_data + slirp->if_mtu - (resp + 2); slen = snprintf((char *)resp + 2, smaxlen, "tftp://[%02x%02x:%02x%02x:%02x%02x:%02x%02x:" "%02x%02x:%02x%02x:%02x%02x:%02x%02x]/%s", @@ -11,8 +11,12 @@ #define IF_AUTOCOMP 0x04 /* Autodetect (default) */ #define IF_NOCIDCOMP 0x08 /* CID compression */ -#define IF_MTU 1500 -#define IF_MRU 1500 +#define IF_MTU_DEFAULT 1500 +#define IF_MTU_MIN 68 +#define IF_MTU_MAX 65521 +#define IF_MRU_DEFAULT 1500 +#define IF_MRU_MIN 68 +#define IF_MRU_MAX 65521 #define IF_COMP IF_AUTOCOMP /* Flags for compression */ /* 2 for alignment, 14 for ethernet */ diff --git a/src/ip6_icmp.c b/src/ip6_icmp.c index 8512686..28ec2be 100644 --- a/src/ip6_icmp.c +++ b/src/ip6_icmp.c @@ -94,8 +94,8 @@ void icmp6_send_error(struct mbuf *m, uint8_t type, uint8_t code) DEBUG_ARG("target = %s", addrstr); rip->ip_nh = IPPROTO_ICMPV6; - const int error_data_len = - MIN(m->m_len, IF_MTU - (sizeof(struct ip6) + ICMP6_ERROR_MINLEN)); + const int error_data_len = MIN( + m->m_len, slirp->if_mtu - (sizeof(struct ip6) + ICMP6_ERROR_MINLEN)); rip->ip_pl = htons(ICMP6_ERROR_MINLEN + error_data_len); t->m_len = sizeof(struct ip6) + ntohs(rip->ip_pl); @@ -112,7 +112,7 @@ void icmp6_send_error(struct mbuf *m, uint8_t type, uint8_t code) ricmp->icmp6_err.unused = 0; break; case ICMP6_TOOBIG: - ricmp->icmp6_err.mtu = htonl(IF_MTU); + ricmp->icmp6_err.mtu = htonl(slirp->if_mtu); break; case ICMP6_PARAMPROB: /* TODO: Handle this case */ diff --git a/src/ip6_input.c b/src/ip6_input.c index d9d2b7e..dfcbfd6 100644 --- a/src/ip6_input.c +++ b/src/ip6_input.c @@ -44,7 +44,7 @@ void ip6_input(struct mbuf *m) goto bad; } - if (ntohs(ip6->ip_pl) > IF_MTU) { + if (ntohs(ip6->ip_pl) > slirp->if_mtu) { icmp6_send_error(m, ICMP6_TOOBIG, 0); goto bad; } diff --git a/src/ip_output.c b/src/ip_output.c index f820359..22916a3 100644 --- a/src/ip_output.c +++ b/src/ip_output.c @@ -72,7 +72,7 @@ int ip_output(struct socket *so, struct mbuf *m0) /* * If small enough for interface, can just send directly. */ - if ((uint16_t)ip->ip_len <= IF_MTU) { + if ((uint16_t)ip->ip_len <= slirp->if_mtu) { ip->ip_len = htons((uint16_t)ip->ip_len); ip->ip_off = htons((uint16_t)ip->ip_off); ip->ip_sum = 0; @@ -91,7 +91,7 @@ int ip_output(struct socket *so, struct mbuf *m0) goto bad; } - len = (IF_MTU - hlen) & ~7; /* ip databytes per packet */ + len = (slirp->if_mtu - hlen) & ~7; /* ip databytes per packet */ if (len < 8) { error = -1; goto bad; diff --git a/src/libslirp.h b/src/libslirp.h index ba6a142..2ba4388 100644 --- a/src/libslirp.h +++ b/src/libslirp.h @@ -85,6 +85,10 @@ typedef struct SlirpConfig { struct in6_addr vnameserver6; const char **vdnssearch; const char *vdomainname; + /* Default: IF_MTU_DEFAULT */ + size_t if_mtu; + /* Default: IF_MRU_DEFAULT */ + size_t if_mru; } SlirpConfig; Slirp *slirp_new(const SlirpConfig *cfg, const SlirpCb *callbacks, @@ -20,8 +20,8 @@ /* * Find a nice value for msize */ -#define SLIRP_MSIZE \ - (offsetof(struct mbuf, m_dat) + IF_MAXLINKHDR + TCPIPHDR_DELTA + IF_MTU) +#define SLIRP_MSIZE(mtu) \ + (offsetof(struct mbuf, m_dat) + IF_MAXLINKHDR + TCPIPHDR_DELTA + (mtu)) void m_init(Slirp *slirp) { @@ -66,7 +66,7 @@ struct mbuf *m_get(Slirp *slirp) DEBUG_CALL("m_get"); if (slirp->m_freelist.qh_link == &slirp->m_freelist) { - m = g_malloc(SLIRP_MSIZE); + m = g_malloc(SLIRP_MSIZE(slirp->if_mtu)); slirp->mbuf_alloced++; if (slirp->mbuf_alloced > MBUF_THRESH) flags = M_DOFREE; @@ -81,7 +81,7 @@ struct mbuf *m_get(Slirp *slirp) m->m_flags = (flags | M_USEDLIST); /* Initialise it */ - m->m_size = SLIRP_MSIZE - offsetof(struct mbuf, m_dat); + m->m_size = SLIRP_MSIZE(slirp->if_mtu) - offsetof(struct mbuf, m_dat); m->m_data = m->m_dat; m->m_len = 0; m->m_nextpkt = NULL; diff --git a/src/slirp.c b/src/slirp.c index c82f675..3be982c 100644 --- a/src/slirp.c +++ b/src/slirp.c @@ -271,6 +271,10 @@ Slirp *slirp_new(const SlirpConfig *cfg, const SlirpCb *callbacks, void *opaque) { Slirp *slirp; g_return_val_if_fail(cfg != NULL, NULL); + g_return_val_if_fail(cfg->if_mtu >= IF_MTU_MIN || cfg->if_mtu == 0, NULL); + g_return_val_if_fail(cfg->if_mtu <= IF_MTU_MAX, NULL); + g_return_val_if_fail(cfg->if_mru >= IF_MRU_MIN || cfg->if_mru == 0, NULL); + g_return_val_if_fail(cfg->if_mru <= IF_MRU_MAX, NULL); slirp = g_malloc0(sizeof(Slirp)); @@ -311,6 +315,8 @@ Slirp *slirp_new(const SlirpConfig *cfg, const SlirpCb *callbacks, void *opaque) if (cfg->vdnssearch) { translate_dnssearch(slirp, cfg->vdnssearch); } + slirp->if_mtu = cfg->if_mtu == 0 ? IF_MTU_DEFAULT : cfg->if_mtu; + slirp->if_mru = cfg->if_mru == 0 ? IF_MRU_DEFAULT : cfg->if_mru; return slirp; } @@ -917,7 +923,7 @@ static int if_encap6(Slirp *slirp, struct mbuf *ifm, struct ethhdr *eh, */ int if_encap(Slirp *slirp, struct mbuf *ifm) { - uint8_t buf[1600]; + uint8_t buf[IF_MTU_MAX + 100]; struct ethhdr *eh = (struct ethhdr *)buf; uint8_t ethaddr[ETH_ALEN]; const struct ip *iph = (const struct ip *)ifm->m_data; diff --git a/src/slirp.h b/src/slirp.h index 37ba6ed..5fbee5c 100644 --- a/src/slirp.h +++ b/src/slirp.h @@ -144,6 +144,9 @@ struct Slirp { int restricted; struct gfwd_list *guestfwd_list; + int if_mtu; + int if_mru; + /* mbuf states */ struct quehead m_freelist; struct quehead m_usedlist; @@ -41,8 +41,9 @@ typedef uint32_t tcp_seq; #define PR_SLOWHZ 2 /* 2 slow timeouts per second (approx) */ #define PR_FASTHZ 5 /* 5 fast timeouts per second (not important) */ -#define TCP_SNDSPACE 8192 -#define TCP_RCVSPACE 8192 +#define TCP_SNDSPACE 1024 * 128 +#define TCP_RCVSPACE 1024 * 128 +#define TCP_MAXSEG_MAX 32768 /* * TCP header. @@ -100,19 +101,6 @@ struct tcphdr { #define TCPOLEN_TSTAMP_APPA (TCPOLEN_TIMESTAMP + 2) /* appendix A */ #endif -/* - * Default maximum segment size for TCP. - * With an IP MSS of 576, this is 536, - * but 512 is probably more convenient. - * This should be defined as MIN(512, IP_MSS - sizeof (struct tcpiphdr)). - * - * We make this 1460 because we only care about Ethernet in the qemu context. - */ -#undef TCP_MSS -#define TCP_MSS 1460 -#undef TCP6_MSS -#define TCP6_MSS 1440 - #undef TCP_MAXWIN #define TCP_MAXWIN 65535 /* largest value for (unscaled) window */ diff --git a/src/tcp_input.c b/src/tcp_input.c index 228c2aa..30265d6 100644 --- a/src/tcp_input.c +++ b/src/tcp_input.c @@ -1510,10 +1510,12 @@ int tcp_mss(struct tcpcb *tp, unsigned offer) switch (so->so_ffamily) { case AF_INET: - mss = MIN(IF_MTU, IF_MRU) - sizeof(struct tcphdr) - sizeof(struct ip); + mss = MIN(so->slirp->if_mtu, so->slirp->if_mru) - + sizeof(struct tcphdr) - sizeof(struct ip); break; case AF_INET6: - mss = MIN(IF_MTU, IF_MRU) - sizeof(struct tcphdr) - sizeof(struct ip6); + mss = MIN(so->slirp->if_mtu, so->slirp->if_mru) - + sizeof(struct tcphdr) - sizeof(struct ip6); break; default: g_assert_not_reached(); @@ -1523,7 +1525,7 @@ int tcp_mss(struct tcpcb *tp, unsigned offer) mss = MIN(mss, offer); mss = MAX(mss, 32); if (mss < tp->t_maxseg || offer != 0) - tp->t_maxseg = mss; + tp->t_maxseg = MIN(mss, TCP_MAXSEG_MAX); tp->snd_cwnd = mss; diff --git a/src/tcp_subr.c b/src/tcp_subr.c index d6dd133..83c7520 100644 --- a/src/tcp_subr.c +++ b/src/tcp_subr.c @@ -261,7 +261,13 @@ struct tcpcb *tcp_newtcpcb(struct socket *so) memset((char *)tp, 0, sizeof(struct tcpcb)); tp->seg_next = tp->seg_prev = (struct tcpiphdr *)tp; - tp->t_maxseg = (so->so_ffamily == AF_INET) ? TCP_MSS : TCP6_MSS; + /* + * 40: length of IPv4 header (20) + TCP header (20) + * 60: length of IPv6 header (40) + TCP header (20) + */ + tp->t_maxseg = + MIN(so->slirp->if_mtu - ((so->so_ffamily == AF_INET) ? 40 : 60), + TCP_MAXSEG_MAX); tp->t_flags = TCP_DO_RFC1323 ? (TF_REQ_SCALE | TF_REQ_TSTMP) : 0; tp->t_socket = so; |