On 14.02.2016 18:47, Samuel Thibault wrote: > From: Yann Bordenave <m...@meowstars.org> > > This patch adds parameters to manage some new options in the qemu -net > command. > Slirp IPv6 address, network prefix, and DNS IPv6 address can be given in > argument to the qemu command. > Defaults parameters are respectively fec0::2, fec0::, /64 and fec0::3. > > Signed-off-by: Yann Bordenave <m...@meowstars.org> > Signed-off-by: Samuel Thibault <samuel.thiba...@ens-lyon.org> > --- > net/net.c | 31 +++++++++++++++++++++++++++++++ > net/slirp.c | 50 ++++++++++++++++++++++++++++++++++++++++++++------ > qapi-schema.json | 40 ++++++++++++++++++++++++++-------------- > qemu-options.hx | 18 ++++++++++++++++-- > slirp/libslirp.h | 8 +++++--- > slirp/slirp.c | 16 +++++++++------- > 6 files changed, 131 insertions(+), 32 deletions(-) > > diff --git a/net/net.c b/net/net.c > index c5e414f..a097971 100644 > --- a/net/net.c > +++ b/net/net.c > @@ -1060,6 +1060,37 @@ int net_client_init(QemuOpts *opts, int is_netdev, > Error **errp) > int ret = -1; > > { > + /* Parse convenience option format ip6-net=fec0::0[/64] */ > + const char *ip6_net = qemu_opt_get(opts, "ip6-net"); > + > + if (ip6_net) { > + char buf[strlen(ip6_net) + 1]; > + > + if (get_str_sep(buf, sizeof(buf), &ip6_net, '/') < 0) { > + /* Default 64bit prefix length. */ > + qemu_opt_set(opts, "ip6-prefix", ip6_net, &error_abort); > + qemu_opt_set_number(opts, "ip6-prefixlen", 64, &error_abort); > + } else { > + /* User-specified prefix length. */ > + unsigned long len; > + int err; > + > + qemu_opt_set(opts, "ip6-prefix", buf, &error_abort); > + err = qemu_strtoul(ip6_net, NULL, 10, &len); > + > + if (err) { > + error_setg(errp, QERR_INVALID_PARAMETER_VALUE, > + "ip6-prefix", "a number"); > + } else { > + qemu_opt_set_number(opts, "ip6-prefixlen", len, > + &error_abort); > + } > + } > + qemu_opt_unset(opts, "ip6-net"); > + } > + } > + > + { > OptsVisitor *ov = opts_visitor_new(opts); > > net_visit(opts_get_visitor(ov), is_netdev, &object, &err); > diff --git a/net/slirp.c b/net/slirp.c > index 6b51fbc..076dd27 100644 > --- a/net/slirp.c > +++ b/net/slirp.c > @@ -135,17 +135,23 @@ static NetClientInfo net_slirp_info = { > static int net_slirp_init(NetClientState *peer, const char *model, > const char *name, int restricted, > const char *vnetwork, const char *vhost, > + const char *vprefix6, int vprefix6_len, > + const char *vhost6, > const char *vhostname, const char *tftp_export, > const char *bootfile, const char *vdhcp_start, > - const char *vnameserver, const char *smb_export, > - const char *vsmbserver, const char **dnssearch) > + const char *vnameserver, const char *vnameserver6, > + const char *smb_export, const char *vsmbserver, > + const char **dnssearch) > { > /* default settings according to historic slirp */ > struct in_addr net = { .s_addr = htonl(0x0a000200) }; /* 10.0.2.0 */ > struct in_addr mask = { .s_addr = htonl(0xffffff00) }; /* 255.255.255.0 > */ > struct in_addr host = { .s_addr = htonl(0x0a000202) }; /* 10.0.2.2 */ > + struct in6_addr ip6_prefix; > + struct in6_addr ip6_host; > struct in_addr dhcp = { .s_addr = htonl(0x0a00020f) }; /* 10.0.2.15 */ > struct in_addr dns = { .s_addr = htonl(0x0a000203) }; /* 10.0.2.3 */ > + struct in6_addr ip6_dns; > #ifndef _WIN32 > struct in_addr smbsrv = { .s_addr = 0 }; > #endif > @@ -213,6 +219,27 @@ static int net_slirp_init(NetClientState *peer, const > char *model, > return -1; > } > > + if (!vprefix6) { > + vprefix6 = "fec0::"; > + } > + if (!inet_pton(AF_INET6, vprefix6, &ip6_prefix)) { > + return -1; > + } > + > + if (!vprefix6_len) { > + vprefix6_len = 64; > + } > + if (vprefix6_len < 0 || vprefix6_len > 128) { > + return -1; > + } > + > + if (!vhost6) { > + vhost6 = "fec0::2"; > + } > + if (!inet_pton(AF_INET6, vhost6, &ip6_host)) { > + return -1; > + }
The IPv4 code seems to have a sanity check that the vhost address is within the same net as specified with the "net=" parameter... maybe the IPv6 part should have that, too? Or use the prefix from "ip6-net=" here if ip6-host has not been specified manually? > if (vnameserver && !inet_aton(vnameserver, &dns)) { > return -1; > } > @@ -221,6 +248,13 @@ static int net_slirp_init(NetClientState *peer, const > char *model, > return -1; > } > > + if (!vnameserver6) { > + vnameserver6 = "fec0::3"; > + } > + if (!inet_pton(AF_INET6, vnameserver6, &ip6_dns)) { > + return -1; > + } dito? > if (vdhcp_start && !inet_aton(vdhcp_start, &dhcp)) { > return -1; > } > @@ -243,8 +277,10 @@ static int net_slirp_init(NetClientState *peer, const > char *model, > > s = DO_UPCAST(SlirpState, nc, nc); > > - s->slirp = slirp_init(restricted, net, mask, host, vhostname, > - tftp_export, bootfile, dhcp, dns, dnssearch, s); > + s->slirp = slirp_init(restricted, net, mask, host, > + ip6_prefix, vprefix6_len, ip6_host, > + vhostname, tftp_export, bootfile, dhcp, > + dns, ip6_dns, dnssearch, s); > QTAILQ_INSERT_TAIL(&slirp_stacks, s, entry); > > for (config = slirp_configs; config; config = config->next) { > @@ -761,8 +797,10 @@ int net_init_slirp(const NetClientOptions *opts, const > char *name, > net_init_slirp_configs(user->guestfwd, 0); > > ret = net_slirp_init(peer, "user", name, user->q_restrict, vnet, > - user->host, user->hostname, user->tftp, > - user->bootfile, user->dhcpstart, user->dns, > user->smb, > + user->host, user->ip6_prefix, user->ip6_prefixlen, > + user->ip6_host, user->hostname, user->tftp, > + user->bootfile, user->dhcpstart, > + user->dns, user->ip6_dns, user->smb, > user->smbserver, dnssearch); > > while (slirp_configs) { > diff --git a/qapi-schema.json b/qapi-schema.json > index 8d04897..a62c2ec 100644 > --- a/qapi-schema.json > +++ b/qapi-schema.json > @@ -2399,6 +2399,14 @@ > # @dnssearch: #optional list of DNS suffixes to search, passed as DHCP option > # to the guest > # > +# @ip6-prefix: #optional IPv6 network prefix (default is fec0::) (since 2.6) > +# > +# @ip6-prefixlen: #optional IPv6 network prefix length (default is 64) > (since 2.6) > +# > +# @ip6-host: #optional guest-visible IPv6 address of the host (since 2.6) > +# > +# @ip6-dns: #optional guest-visible IPv6 address of the virtual nameserver > (since 2.6) > +# > # @smb: #optional root directory of the built-in SMB server > # > # @smbserver: #optional IP address of the built-in SMB server > @@ -2412,20 +2420,24 @@ > ## > { 'struct': 'NetdevUserOptions', > 'data': { > - '*hostname': 'str', > - '*restrict': 'bool', > - '*ip': 'str', > - '*net': 'str', > - '*host': 'str', > - '*tftp': 'str', > - '*bootfile': 'str', > - '*dhcpstart': 'str', > - '*dns': 'str', > - '*dnssearch': ['String'], > - '*smb': 'str', > - '*smbserver': 'str', > - '*hostfwd': ['String'], > - '*guestfwd': ['String'] } } > + '*hostname': 'str', > + '*restrict': 'bool', > + '*ip': 'str', > + '*net': 'str', > + '*host': 'str', > + '*tftp': 'str', > + '*bootfile': 'str', > + '*dhcpstart': 'str', > + '*dns': 'str', > + '*dnssearch': ['String'], > + '*ip6-prefix': 'str', > + '*ip6-prefixlen': 'int', > + '*ip6-host': 'str', > + '*ip6-dns': 'str', > + '*smb': 'str', > + '*smbserver': 'str', > + '*hostfwd': ['String'], > + '*guestfwd': ['String'] } } > > ## > # @NetdevTapOptions > diff --git a/qemu-options.hx b/qemu-options.hx > index 733a194..de9e314 100644 > --- a/qemu-options.hx > +++ b/qemu-options.hx > @@ -1542,8 +1542,9 @@ DEF("smb", HAS_ARG, QEMU_OPTION_smb, "", QEMU_ARCH_ALL) > > DEF("netdev", HAS_ARG, QEMU_OPTION_netdev, > #ifdef CONFIG_SLIRP > - "-netdev user,id=str[,net=addr[/mask]][,host=addr][,restrict=on|off]\n" > - " > [,hostname=host][,dhcpstart=addr][,dns=addr][,dnssearch=domain][,tftp=dir]\n" > + "-netdev > user,id=str[,net=addr[/mask]][,host=addr][,ip6-net=addr[/int]]\n" > + " > [,ip6-host=addr][,restrict=on|off][,hostname=host][,dhcpstart=addr]\n" > + " [,dns=addr][,ip6-dns=addr][,dnssearch=domain][,tftp=dir]\n" > " [,bootfile=f][,hostfwd=rule][,guestfwd=rule]" > #ifndef _WIN32 > "[,smb=dir[,smbserver=addr]]\n" > @@ -1700,6 +1701,14 @@ either in the form a.b.c.d or as number of valid > top-most bits. Default is > Specify the guest-visible address of the host. Default is the 2nd IP in the > guest network, i.e. x.x.x.2. > > +@item ip6-net=@var{addr}[/@var{int}] > +Set IPv6 network address the guest will see. Optionally specify the prefix > +size, as number of valid top-most bits. Default is fec0::/64. > + > +@item ip6-host=@var{addr} > +Specify the guest-visible IPv6 address of the host. Default is the 2nd IPv6 > in > +the guest network, i.e. xxxx::2. At least this does currently not match the code - the current default is always fec0::2, no matter what has been specified for "ip6-net=...". > @item restrict=on|off > If this option is enabled, the guest will be isolated, i.e. it will not be > able to contact the host and no guest IP packets will be routed over the host > @@ -1717,6 +1726,11 @@ Specify the guest-visible address of the virtual > nameserver. The address must > be different from the host address. Default is the 3rd IP in the guest > network, > i.e. x.x.x.3. > > +@item ip6-dns=@var{addr} > +Specify the guest-visible address of the IPv6 virtual nameserver. The address > +must be different from the host address. Default is the 3rd IP in the guest > +network, i.e. xxxx::3. dito > @item dnssearch=@var{domain} > Provides an entry for the domain-search list sent by the built-in > DHCP server. More than one domain suffix can be transmitted by specifying ... The other parts of the patch look good to me. Thomas