slirp updates
Alexey Kardashevskiy slirp: Improve debugging messages Andreas Gustafsson, Samuel Thibault, James Clarke slirp: Improve bandwidth in GDB remote debugging and FreeBSD guests Benjamin Drung: slirp/dhcp: Add domainname option Cédric Le Goater (3): slirp/ncsi: fix "Get Version ID" payload length slirp/ncsi: add a "Get Parameters" response slirp/ncsi: add checksum support Nia Alarie: net/slirp: Convert atoi to qemu_strtoi to allow error checking -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEOjpdRkZg6GdhDKQnmWhJwc9WBHgFAlsRUCUACgkQmWhJwc9W BHhQvw//cxMU8DKvmntxBIA1FCCkFbw12PjiV2w3HELaWyA4MfZVWaqrCOhM/uuY 2Woi2qcgqK1UTlhHpKufg3LnEFZwyU+t9IxuNCmk7hb+GeIEndhEv9jzvHbJuoaI Va+Ka6hTHc5fAAs9YDQu9Je77HgeaRyH1ER/l3wEZf5lxGy5VBHBqUV2LCJUrtvA 7RWxOQM380fzs8hSM/7I6V6XVplbD1bUfbCsOmatbq4X95ww/5JKTawx8Uxr6mie BbDGO7fJhshXiBn7CQ/v+C3O9GsGmfxQu78EE1GaLseP7ZKdOpDLVrfj70fLJ+ZS RdywIeorEmkFdSWLBp0GTfbmdp7fGTL+zAlos+nO1cw83I98qibwgVCZuDOM/lkh Xyp+hMlRWNl9YiXjtxoMKEapw0S8J5w0O9Z8AjPW9XZOCgzHhl8Sfli/5iA7ATfT zwBWrIsZLffE+hCmfDD0X9kJtvYTp+qV+gDbXW1OGivhcz+4Kq3UGH89ZGtPBlQt +J6uZV8vq5PXaT6SvaVFaau0Owuqyc7pbvcdebBaq76mgPoYZIhA7LDU3Ghg3kC6 AQPdeid4d6/9sMSlJxVQqz0VqxOCpe58WKJelmCub0xBNMy0fLT7S2mX8mb3Hsvg p9ep/h7d0McbBRJH1jxhIFpGvSEdHKxOtv7hACrfw+39106QvWk= =FEM+ -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/thibault/tags/samuel-thibault' into staging slirp updates Alexey Kardashevskiy slirp: Improve debugging messages Andreas Gustafsson, Samuel Thibault, James Clarke slirp: Improve bandwidth in GDB remote debugging and FreeBSD guests Benjamin Drung: slirp/dhcp: Add domainname option Cédric Le Goater (3): slirp/ncsi: fix "Get Version ID" payload length slirp/ncsi: add a "Get Parameters" response slirp/ncsi: add checksum support Nia Alarie: net/slirp: Convert atoi to qemu_strtoi to allow error checking # gpg: Signature made Fri 01 Jun 2018 14:54:45 BST # gpg: using RSA key 996849C1CF560478 # gpg: Good signature from "Samuel Thibault <samuel.thibault@aquilenet.fr>" # gpg: aka "Samuel Thibault <sthibault@debian.org>" # gpg: aka "Samuel Thibault <samuel.thibault@gnu.org>" # gpg: aka "Samuel Thibault <samuel.thibault@inria.fr>" # gpg: aka "Samuel Thibault <samuel.thibault@labri.fr>" # gpg: aka "Samuel Thibault <samuel.thibault@ens-lyon.org>" # gpg: aka "Samuel Thibault <samuel.thibault@u-bordeaux.fr>" # gpg: WARNING: This key is not certified with sufficiently trusted signatures! # gpg: It is not certain that the signature belongs to the owner. # Primary key fingerprint: 900C B024 B679 31D4 0F82 304B D017 8C76 7D06 9EE6 # Subkey fingerprint: 3A3A 5D46 4660 E867 610C A427 9968 49C1 CF56 0478 * remotes/thibault/tags/samuel-thibault: slirp/ncsi: add checksum support slirp/ncsi: add a "Get Parameters" response slirp/ncsi: fix "Get Version ID" payload length slirp: Send window updates to guest after window was closed net/slirp: Convert atoi to qemu_strtoi to allow error checking slirp/debug: Print IP addresses in human readable form slirp: disable Nagle in ingoing connections slirp: disable Nagle in outgoing connections slirp: Add domainname option to slirp's DHCP server Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
9be4af1330
16
net/slirp.c
16
net/slirp.c
@ -157,7 +157,8 @@ static int net_slirp_init(NetClientState *peer, const char *model,
|
||||
const char *bootfile, const char *vdhcp_start,
|
||||
const char *vnameserver, const char *vnameserver6,
|
||||
const char *smb_export, const char *vsmbserver,
|
||||
const char **dnssearch, Error **errp)
|
||||
const char **dnssearch, const char *vdomainname,
|
||||
Error **errp)
|
||||
{
|
||||
/* default settings according to historic slirp */
|
||||
struct in_addr net = { .s_addr = htonl(0x0a000200) }; /* 10.0.2.0 */
|
||||
@ -359,6 +360,11 @@ static int net_slirp_init(NetClientState *peer, const char *model,
|
||||
ip6_dns.s6_addr[15] |= 3;
|
||||
}
|
||||
|
||||
if (vdomainname && !*vdomainname) {
|
||||
error_setg(errp, "'domainname' parameter cannot be empty");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
nc = qemu_new_net_client(&net_slirp_info, peer, model, name);
|
||||
|
||||
@ -371,7 +377,7 @@ static int net_slirp_init(NetClientState *peer, const char *model,
|
||||
s->slirp = slirp_init(restricted, ipv4, net, mask, host,
|
||||
ipv6, ip6_prefix, vprefix6_len, ip6_host,
|
||||
vhostname, tftp_export, bootfile, dhcp,
|
||||
dns, ip6_dns, dnssearch, s);
|
||||
dns, ip6_dns, dnssearch, vdomainname, s);
|
||||
QTAILQ_INSERT_TAIL(&slirp_stacks, s, entry);
|
||||
|
||||
for (config = slirp_configs; config; config = config->next) {
|
||||
@ -486,7 +492,9 @@ void hmp_hostfwd_remove(Monitor *mon, const QDict *qdict)
|
||||
goto fail_syntax;
|
||||
}
|
||||
|
||||
host_port = atoi(p);
|
||||
if (qemu_strtoi(p, NULL, 10, &host_port)) {
|
||||
goto fail_syntax;
|
||||
}
|
||||
|
||||
err = slirp_remove_hostfwd(s->slirp, is_udp, host_addr, host_port);
|
||||
|
||||
@ -958,7 +966,7 @@ int net_init_slirp(const Netdev *netdev, const char *name,
|
||||
user->ipv6_host, user->hostname, user->tftp,
|
||||
user->bootfile, user->dhcpstart,
|
||||
user->dns, user->ipv6_dns, user->smb,
|
||||
user->smbserver, dnssearch, errp);
|
||||
user->smbserver, dnssearch, user->domainname, errp);
|
||||
|
||||
while (slirp_configs) {
|
||||
config = slirp_configs;
|
||||
|
@ -160,6 +160,9 @@
|
||||
# @dnssearch: list of DNS suffixes to search, passed as DHCP option
|
||||
# to the guest
|
||||
#
|
||||
# @domainname: guest-visible domain name of the virtual nameserver
|
||||
# (since 2.12)
|
||||
#
|
||||
# @ipv6-prefix: IPv6 network prefix (default is fec0::) (since
|
||||
# 2.6). The network prefix is given in the usual
|
||||
# hexadecimal IPv6 address notation.
|
||||
@ -197,6 +200,7 @@
|
||||
'*dhcpstart': 'str',
|
||||
'*dns': 'str',
|
||||
'*dnssearch': ['String'],
|
||||
'*domainname': 'str',
|
||||
'*ipv6-prefix': 'str',
|
||||
'*ipv6-prefixlen': 'int',
|
||||
'*ipv6-host': 'str',
|
||||
|
@ -1906,8 +1906,8 @@ DEF("netdev", HAS_ARG, QEMU_OPTION_netdev,
|
||||
"-netdev user,id=str[,ipv4[=on|off]][,net=addr[/mask]][,host=addr]\n"
|
||||
" [,ipv6[=on|off]][,ipv6-net=addr[/int]][,ipv6-host=addr]\n"
|
||||
" [,restrict=on|off][,hostname=host][,dhcpstart=addr]\n"
|
||||
" [,dns=addr][,ipv6-dns=addr][,dnssearch=domain][,tftp=dir]\n"
|
||||
" [,bootfile=f][,hostfwd=rule][,guestfwd=rule]"
|
||||
" [,dns=addr][,ipv6-dns=addr][,dnssearch=domain][,domainname=domain]\n"
|
||||
" [,tftp=dir][,bootfile=f][,hostfwd=rule][,guestfwd=rule]"
|
||||
#ifndef _WIN32
|
||||
"[,smb=dir[,smbserver=addr]]\n"
|
||||
#endif
|
||||
@ -2135,6 +2135,9 @@ Example:
|
||||
qemu-system-i386 -nic user,dnssearch=mgmt.example.org,dnssearch=example.org
|
||||
@end example
|
||||
|
||||
@item domainname=@var{domain}
|
||||
Specifies the client domain name reported by the built-in DHCP server.
|
||||
|
||||
@item tftp=@var{dir}
|
||||
When using the user mode network stack, activate a built-in TFTP
|
||||
server. The files in @var{dir} will be exposed as the root of a TFTP server.
|
||||
|
@ -33,7 +33,7 @@ void arp_table_add(Slirp *slirp, uint32_t ip_addr, uint8_t ethaddr[ETH_ALEN])
|
||||
int i;
|
||||
|
||||
DEBUG_CALL("arp_table_add");
|
||||
DEBUG_ARG("ip = %s", inet_ntoa(*(struct in_addr *)&ip_addr));
|
||||
DEBUG_ARG("ip = %s", inet_ntoa((struct in_addr){.s_addr = ip_addr}));
|
||||
DEBUG_ARGS((dfd, " hw addr = %02x:%02x:%02x:%02x:%02x:%02x\n",
|
||||
ethaddr[0], ethaddr[1], ethaddr[2],
|
||||
ethaddr[3], ethaddr[4], ethaddr[5]));
|
||||
@ -67,7 +67,7 @@ bool arp_table_search(Slirp *slirp, uint32_t ip_addr,
|
||||
int i;
|
||||
|
||||
DEBUG_CALL("arp_table_search");
|
||||
DEBUG_ARG("ip = %s", inet_ntoa(*(struct in_addr *)&ip_addr));
|
||||
DEBUG_ARG("ip = %s", inet_ntoa((struct in_addr){.s_addr = ip_addr}));
|
||||
|
||||
/* If broadcast address */
|
||||
if (ip_addr == 0xffffffff || ip_addr == broadcast_addr) {
|
||||
|
@ -298,6 +298,14 @@ static void bootp_reply(Slirp *slirp, const struct bootp_t *bp)
|
||||
q += val;
|
||||
}
|
||||
|
||||
if (slirp->vdomainname) {
|
||||
val = strlen(slirp->vdomainname);
|
||||
*q++ = RFC1533_DOMAINNAME;
|
||||
*q++ = val;
|
||||
memcpy(q, slirp->vdomainname, val);
|
||||
q += val;
|
||||
}
|
||||
|
||||
if (slirp->vdnssearch) {
|
||||
size_t spaceleft = sizeof(rbp->bp_vend) - (q - rbp->bp_vend);
|
||||
val = slirp->vdnssearch_len;
|
||||
|
@ -16,7 +16,7 @@ Slirp *slirp_init(int restricted, bool in_enabled, struct in_addr vnetwork,
|
||||
const char *tftp_path, const char *bootfile,
|
||||
struct in_addr vdhcp_start, struct in_addr vnameserver,
|
||||
struct in6_addr vnameserver6, const char **vdnssearch,
|
||||
void *opaque);
|
||||
const char *vdomainname, void *opaque);
|
||||
void slirp_cleanup(Slirp *slirp);
|
||||
|
||||
void slirp_pollfds_fill(GArray *pollfds, uint32_t *timeout);
|
||||
|
51
slirp/ncsi.c
51
slirp/ncsi.c
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* NC-SI (Network Controller Sideband Interface) "echo" model
|
||||
*
|
||||
* Copyright (C) 2016 IBM Corp.
|
||||
* Copyright (C) 2016-2018 IBM Corp.
|
||||
*
|
||||
* This code is licensed under the GPL version 2 or later. See the
|
||||
* COPYING file in the top-level directory.
|
||||
@ -11,6 +11,23 @@
|
||||
|
||||
#include "ncsi-pkt.h"
|
||||
|
||||
static uint32_t ncsi_calculate_checksum(uint16_t *data, int len)
|
||||
{
|
||||
uint32_t checksum = 0;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* 32-bit unsigned sum of the NC-SI packet header and NC-SI packet
|
||||
* payload interpreted as a series of 16-bit unsigned integer values.
|
||||
*/
|
||||
for (i = 0; i < len; i++) {
|
||||
checksum += htons(data[i]);
|
||||
}
|
||||
|
||||
checksum = (~checksum + 1);
|
||||
return checksum;
|
||||
}
|
||||
|
||||
/* Get Capabilities */
|
||||
static int ncsi_rsp_handler_gc(struct ncsi_rsp_pkt_hdr *rnh)
|
||||
{
|
||||
@ -35,6 +52,20 @@ static int ncsi_rsp_handler_gls(struct ncsi_rsp_pkt_hdr *rnh)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Get Parameters */
|
||||
static int ncsi_rsp_handler_gp(struct ncsi_rsp_pkt_hdr *rnh)
|
||||
{
|
||||
struct ncsi_rsp_gp_pkt *rsp = (struct ncsi_rsp_gp_pkt *) rnh;
|
||||
|
||||
/* no MAC address filters or VLAN filters on the channel */
|
||||
rsp->mac_cnt = 0;
|
||||
rsp->mac_enable = 0;
|
||||
rsp->vlan_cnt = 0;
|
||||
rsp->vlan_enable = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct ncsi_rsp_handler {
|
||||
unsigned char type;
|
||||
int payload;
|
||||
@ -60,9 +91,9 @@ static const struct ncsi_rsp_handler {
|
||||
{ NCSI_PKT_RSP_EGMF, 4, NULL },
|
||||
{ NCSI_PKT_RSP_DGMF, 4, NULL },
|
||||
{ NCSI_PKT_RSP_SNFC, 4, NULL },
|
||||
{ NCSI_PKT_RSP_GVI, 36, NULL },
|
||||
{ NCSI_PKT_RSP_GVI, 40, NULL },
|
||||
{ NCSI_PKT_RSP_GC, 32, ncsi_rsp_handler_gc },
|
||||
{ NCSI_PKT_RSP_GP, -1, NULL },
|
||||
{ NCSI_PKT_RSP_GP, 40, ncsi_rsp_handler_gp },
|
||||
{ NCSI_PKT_RSP_GCPS, 172, NULL },
|
||||
{ NCSI_PKT_RSP_GNS, 172, NULL },
|
||||
{ NCSI_PKT_RSP_GNPTS, 172, NULL },
|
||||
@ -87,6 +118,9 @@ void ncsi_input(Slirp *slirp, const uint8_t *pkt, int pkt_len)
|
||||
(ncsi_reply + ETH_HLEN);
|
||||
const struct ncsi_rsp_handler *handler = NULL;
|
||||
int i;
|
||||
int ncsi_rsp_len = sizeof(*nh);
|
||||
uint32_t checksum;
|
||||
uint32_t *pchecksum;
|
||||
|
||||
memset(ncsi_reply, 0, sizeof(ncsi_reply));
|
||||
|
||||
@ -116,15 +150,18 @@ void ncsi_input(Slirp *slirp, const uint8_t *pkt, int pkt_len)
|
||||
/* TODO: handle errors */
|
||||
handler->handler(rnh);
|
||||
}
|
||||
ncsi_rsp_len += handler->payload;
|
||||
} else {
|
||||
rnh->common.length = 0;
|
||||
rnh->code = htons(NCSI_PKT_RSP_C_UNAVAILABLE);
|
||||
rnh->reason = htons(NCSI_PKT_RSP_R_UNKNOWN);
|
||||
}
|
||||
|
||||
/* TODO: add a checksum at the end of the frame but the specs
|
||||
* allows it to be zero */
|
||||
/* Add the optional checksum at the end of the frame. */
|
||||
checksum = ncsi_calculate_checksum((uint16_t *) rnh, ncsi_rsp_len);
|
||||
pchecksum = (uint32_t *)((void *) rnh + ncsi_rsp_len);
|
||||
*pchecksum = htonl(checksum);
|
||||
ncsi_rsp_len += 4;
|
||||
|
||||
slirp_output(slirp->opaque, ncsi_reply, ETH_HLEN + sizeof(*nh) +
|
||||
(handler ? handler->payload : 0) + 4);
|
||||
slirp_output(slirp->opaque, ncsi_reply, ETH_HLEN + ncsi_rsp_len);
|
||||
}
|
||||
|
@ -286,7 +286,7 @@ Slirp *slirp_init(int restricted, bool in_enabled, struct in_addr vnetwork,
|
||||
const char *tftp_path, const char *bootfile,
|
||||
struct in_addr vdhcp_start, struct in_addr vnameserver,
|
||||
struct in6_addr vnameserver6, const char **vdnssearch,
|
||||
void *opaque)
|
||||
const char *vdomainname, void *opaque)
|
||||
{
|
||||
Slirp *slirp = g_malloc0(sizeof(Slirp));
|
||||
|
||||
@ -317,6 +317,7 @@ Slirp *slirp_init(int restricted, bool in_enabled, struct in_addr vnetwork,
|
||||
}
|
||||
slirp->tftp_prefix = g_strdup(tftp_path);
|
||||
slirp->bootp_filename = g_strdup(bootfile);
|
||||
slirp->vdomainname = g_strdup(vdomainname);
|
||||
slirp->vdhcp_startaddr = vdhcp_start;
|
||||
slirp->vnameserver_addr = vnameserver;
|
||||
slirp->vnameserver_addr6 = vnameserver6;
|
||||
@ -349,6 +350,7 @@ void slirp_cleanup(Slirp *slirp)
|
||||
g_free(slirp->vdnssearch);
|
||||
g_free(slirp->tftp_prefix);
|
||||
g_free(slirp->bootp_filename);
|
||||
g_free(slirp->vdomainname);
|
||||
g_free(slirp);
|
||||
}
|
||||
|
||||
@ -676,13 +678,13 @@ void slirp_pollfds_poll(GArray *pollfds, int select_error)
|
||||
/* continue; */
|
||||
} else {
|
||||
ret = sowrite(so);
|
||||
if (ret > 0) {
|
||||
/* Call tcp_output in case we need to send a window
|
||||
* update to the guest, otherwise it will be stuck
|
||||
* until it sends a window probe. */
|
||||
tcp_output(sototcpcb(so));
|
||||
}
|
||||
}
|
||||
/*
|
||||
* XXXXX If we wrote something (a lot), there
|
||||
* could be a need for a window update.
|
||||
* In the worst case, the remote will send
|
||||
* a window probe to get things going again
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -193,6 +193,7 @@ struct Slirp {
|
||||
char *bootp_filename;
|
||||
size_t vdnssearch_len;
|
||||
uint8_t *vdnssearch;
|
||||
char *vdomainname;
|
||||
|
||||
/* tcp states */
|
||||
struct socket tcb;
|
||||
|
@ -701,9 +701,9 @@ tcp_listen(Slirp *slirp, uint32_t haddr, u_int hport, uint32_t laddr,
|
||||
memset(&addr, 0, addrlen);
|
||||
|
||||
DEBUG_CALL("tcp_listen");
|
||||
DEBUG_ARG("haddr = %s", inet_ntoa(*(struct in_addr *)&haddr));
|
||||
DEBUG_ARG("haddr = %s", inet_ntoa((struct in_addr){.s_addr = haddr}));
|
||||
DEBUG_ARG("hport = %d", ntohs(hport));
|
||||
DEBUG_ARG("laddr = %s", inet_ntoa(*(struct in_addr *)&laddr));
|
||||
DEBUG_ARG("laddr = %s", inet_ntoa((struct in_addr){.s_addr = laddr}));
|
||||
DEBUG_ARG("lport = %d", ntohs(lport));
|
||||
DEBUG_ARG("flags = %x", flags);
|
||||
|
||||
@ -754,6 +754,8 @@ tcp_listen(Slirp *slirp, uint32_t haddr, u_int hport, uint32_t laddr,
|
||||
return NULL;
|
||||
}
|
||||
qemu_setsockopt(s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(int));
|
||||
opt = 1;
|
||||
qemu_setsockopt(s, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(int));
|
||||
|
||||
getsockname(s,(struct sockaddr *)&addr,&addrlen);
|
||||
so->so_ffamily = AF_INET;
|
||||
|
@ -416,6 +416,8 @@ int tcp_fconnect(struct socket *so, unsigned short af)
|
||||
socket_set_fast_reuse(s);
|
||||
opt = 1;
|
||||
qemu_setsockopt(s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(opt));
|
||||
opt = 1;
|
||||
qemu_setsockopt(s, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt));
|
||||
|
||||
addr = so->fhost.ss;
|
||||
DEBUG_CALL(" connect()ing")
|
||||
|
Loading…
Reference in New Issue
Block a user