aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAkihiro Suda <akihiro.suda.cz@hco.ntt.co.jp>2019-07-10 15:07:37 +0900
committerMarc-André Lureau <marcandre.lureau@redhat.com>2019-08-01 10:57:57 +0400
commit09d410adbff5422b7ba7596bce0ca71f9f807ea9 (patch)
tree65e4ad7ec659bdb091acd65382f58851d7cdd9de /src
parentac916a56bedf449e481c4dc1cda192ca386ff939 (diff)
downloadslirp-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.c2
-rw-r--r--src/if.h8
-rw-r--r--src/ip6_icmp.c6
-rw-r--r--src/ip6_input.c2
-rw-r--r--src/ip_output.c4
-rw-r--r--src/libslirp.h4
-rw-r--r--src/mbuf.c8
-rw-r--r--src/slirp.c8
-rw-r--r--src/slirp.h3
-rw-r--r--src/tcp.h18
-rw-r--r--src/tcp_input.c8
-rw-r--r--src/tcp_subr.c8
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",
diff --git a/src/if.h b/src/if.h
index 3288298..7cf9d27 100644
--- a/src/if.h
+++ b/src/if.h
@@ -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,
diff --git a/src/mbuf.c b/src/mbuf.c
index 4fd6228..54ec721 100644
--- a/src/mbuf.c
+++ b/src/mbuf.c
@@ -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;
diff --git a/src/tcp.h b/src/tcp.h
index 22625e6..70a9760 100644
--- a/src/tcp.h
+++ b/src/tcp.h
@@ -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;