Message ID | 1371820809-19712-1-git-send-email-bas@quarantainenet.nl |
---|---|
State | New |
Headers | show |
On Fri, Jun 21, 2013 at 03:20:09PM +0200, Bas van Sisseren wrote: > The slirp dhcp-server normally returns its own address as tftp > nextserver for netbooting. This patch makes that address > configurable, so it is possible to use an external tftp boot- > environment. > > Signed-off-by: Bas van Sisseren <bas@quarantainenet.nl> > --- > net/slirp.c | 10 ++++++++-- > qapi-schema.json | 3 +++ > qemu-options.hx | 5 ++++- > slirp/bootp.c | 6 +++++- > slirp/libslirp.h | 1 + > slirp/slirp.c | 2 ++ > slirp/slirp.h | 1 + > 7 files changed, 24 insertions(+), 4 deletions(-) CCing Jan Kiszka, the slirp/ maintainer. > diff --git a/net/slirp.c b/net/slirp.c > index 124e953..f3e239c 100644 > --- a/net/slirp.c > +++ b/net/slirp.c > @@ -136,6 +136,7 @@ static int net_slirp_init(NetClientState *peer, const char *model, > const char *vnetwork, const char *vhost, > const char *vhostname, const char *tftp_export, > const char *bootfile, const char *vdhcp_start, > + const char *vnextserver, > const char *vnameserver, const char *smb_export, > const char *vsmbserver, const char **dnssearch) > { > @@ -145,6 +146,7 @@ static int net_slirp_init(NetClientState *peer, const char *model, > struct in_addr host = { .s_addr = htonl(0x0a000202) }; /* 10.0.2.2 */ > 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 in_addr nxtsrv = { .s_addr = 0 }; > #ifndef _WIN32 > struct in_addr smbsrv = { .s_addr = 0 }; > #endif > @@ -228,6 +230,10 @@ static int net_slirp_init(NetClientState *peer, const char *model, > return -1; > } > > + if (vnextserver && !inet_aton(vnextserver, &nxtsrv)) { > + return -1; > + } > + > #ifndef _WIN32 > if (vsmbserver && !inet_aton(vsmbserver, &smbsrv)) { > return -1; > @@ -243,7 +249,7 @@ 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); > + tftp_export, bootfile, dhcp, nxtsrv, dns, dnssearch, s); > QTAILQ_INSERT_TAIL(&slirp_stacks, s, entry); > > for (config = slirp_configs; config; config = config->next) { > @@ -751,7 +757,7 @@ int net_init_slirp(const NetClientOptions *opts, const char *name, > > 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->bootfile, user->dhcpstart, user->nextserver, user->dns, user->smb, > user->smbserver, dnssearch); > > while (slirp_configs) { > diff --git a/qapi-schema.json b/qapi-schema.json > index a80ee40..a8e2c3d 100644 > --- a/qapi-schema.json > +++ b/qapi-schema.json > @@ -2537,6 +2537,8 @@ > # @dhcpstart: #optional the first of the 16 IPs the built-in DHCP server can > # assign > # > +# @nextserver: #optional IP address of BOOTP server > +# > # @dns: #optional guest-visible address of the virtual nameserver > # > # @dnssearch: #optional list of DNS suffixes to search, passed as DHCP option > @@ -2563,6 +2565,7 @@ > '*tftp': 'str', > '*bootfile': 'str', > '*dhcpstart': 'str', > + '*nextserver': 'str', > '*dns': 'str', > '*dnssearch': ['String'], > '*smb': 'str', > diff --git a/qemu-options.hx b/qemu-options.hx > index 8355f9b..8afe42a 100644 > --- a/qemu-options.hx > +++ b/qemu-options.hx > @@ -1350,7 +1350,7 @@ DEF("net", HAS_ARG, QEMU_OPTION_net, > #ifdef CONFIG_SLIRP > "-net user[,vlan=n][,name=str][,net=addr[/mask]][,host=addr][,restrict=on|off]\n" > " [,hostname=host][,dhcpstart=addr][,dns=addr][,dnssearch=domain][,tftp=dir]\n" > - " [,bootfile=f][,hostfwd=rule][,guestfwd=rule]" > + " [,bootfile=f][,nextserver=addr][,hostfwd=rule][,guestfwd=rule]" > #ifndef _WIN32 > "[,smb=dir[,smbserver=addr]]\n" > #endif > @@ -1498,6 +1498,9 @@ When using the user mode network stack, broadcast @var{file} as the BOOTP > filename. In conjunction with @option{tftp}, this can be used to network boot > a guest from a local directory. > > +@item nextserver=@var{addr} > +Specify the IP address of the TFTP server. > + > Example (using pxelinux): > @example > qemu-system-i386 -hda linux.img -boot n -net user,tftp=/path/to/tftp/files,bootfile=/pxelinux.0 > diff --git a/slirp/bootp.c b/slirp/bootp.c > index b7db9fa..d2e89d6 100644 > --- a/slirp/bootp.c > +++ b/slirp/bootp.c > @@ -227,7 +227,11 @@ static void bootp_reply(Slirp *slirp, const struct bootp_t *bp) > memcpy(rbp->bp_hwaddr, bp->bp_hwaddr, ETH_ALEN); > > rbp->bp_yiaddr = daddr.sin_addr; /* Client IP address */ > - rbp->bp_siaddr = saddr.sin_addr; /* Server IP address */ > + if (slirp->vnext_server.s_addr == 0) { > + rbp->bp_siaddr = saddr.sin_addr; /* Server IP address */ > + } else { > + rbp->bp_siaddr = slirp->vnext_server; /* Next-Server address */ > + } > > q = rbp->bp_vend; > memcpy(q, rfc1533_cookie, 4); > diff --git a/slirp/libslirp.h b/slirp/libslirp.h > index ceabff8..c3d800b 100644 > --- a/slirp/libslirp.h > +++ b/slirp/libslirp.h > @@ -12,6 +12,7 @@ Slirp *slirp_init(int restricted, struct in_addr vnetwork, > struct in_addr vnetmask, struct in_addr vhost, > const char *vhostname, const char *tftp_path, > const char *bootfile, struct in_addr vdhcp_start, > + struct in_addr vnext_server, > struct in_addr vnameserver, const char **vdnssearch, > void *opaque); > void slirp_cleanup(Slirp *slirp); > diff --git a/slirp/slirp.c b/slirp/slirp.c > index 80b28ea..35f2afd 100644 > --- a/slirp/slirp.c > +++ b/slirp/slirp.c > @@ -200,6 +200,7 @@ Slirp *slirp_init(int restricted, struct in_addr vnetwork, > struct in_addr vnetmask, struct in_addr vhost, > const char *vhostname, const char *tftp_path, > const char *bootfile, struct in_addr vdhcp_start, > + struct in_addr vnext_server, > struct in_addr vnameserver, const char **vdnssearch, > void *opaque) > { > @@ -225,6 +226,7 @@ Slirp *slirp_init(int restricted, struct in_addr vnetwork, > slirp->tftp_prefix = g_strdup(tftp_path); > slirp->bootp_filename = g_strdup(bootfile); > slirp->vdhcp_startaddr = vdhcp_start; > + slirp->vnext_server = vnext_server; > slirp->vnameserver_addr = vnameserver; > > if (vdnssearch) { > diff --git a/slirp/slirp.h b/slirp/slirp.h > index fe0e65d..a28a8d1 100644 > --- a/slirp/slirp.h > +++ b/slirp/slirp.h > @@ -209,6 +209,7 @@ struct Slirp { > struct in_addr vnetwork_mask; > struct in_addr vhost_addr; > struct in_addr vdhcp_startaddr; > + struct in_addr vnext_server; > struct in_addr vnameserver_addr; > > struct in_addr client_ipaddr; > -- > 1.8.3.1 > >
On 06/21/2013 07:20 AM, Bas van Sisseren wrote: > The slirp dhcp-server normally returns its own address as tftp > nextserver for netbooting. This patch makes that address > configurable, so it is possible to use an external tftp boot- > environment. > > Signed-off-by: Bas van Sisseren <bas@quarantainenet.nl> > --- > net/slirp.c | 10 ++++++++-- > +++ b/qapi-schema.json > @@ -2537,6 +2537,8 @@ > # @dhcpstart: #optional the first of the 16 IPs the built-in DHCP server can > # assign > # > +# @nextserver: #optional IP address of BOOTP server > +# Please mark this field as '(since 1.6)'. Does the field work for both IPv4 and IPv6 addresses? > # @dns: #optional guest-visible address of the virtual nameserver > # > # @dnssearch: #optional list of DNS suffixes to search, passed as DHCP option > @@ -2563,6 +2565,7 @@ > '*tftp': 'str', > '*bootfile': 'str', > '*dhcpstart': 'str', > + '*nextserver': 'str', This is a command addition that libvirt can't take advantage of unless we get introspection working in a timely manner.
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On 01/07/13 22:51, Eric Blake wrote: > On 06/21/2013 07:20 AM, Bas van Sisseren wrote: >> The slirp dhcp-server normally returns its own address as tftp >> nextserver for netbooting. This patch makes that address >> configurable, so it is possible to use an external tftp boot- >> environment. >> >> Signed-off-by: Bas van Sisseren <bas@quarantainenet.nl> >> --- >> net/slirp.c | 10 ++++++++-- > >> +++ b/qapi-schema.json >> @@ -2537,6 +2537,8 @@ >> # @dhcpstart: #optional the first of the 16 IPs the built-in DHCP server can >> # assign >> # >> +# @nextserver: #optional IP address of BOOTP server >> +# > > Please mark this field as '(since 1.6)'. Added in my local checkout. I now have to find out how to generate a new patch and post it into this thread. I'll try to post a new patch somewhere in the next days. (I'm new to git :-) ) > Does the field work for both IPv4 and IPv6 addresses? This setting is IPv4 only. (btw, I think all slirp settings are IPv4 only) >> # @dns: #optional guest-visible address of the virtual nameserver >> # >> # @dnssearch: #optional list of DNS suffixes to search, passed as DHCP option >> @@ -2563,6 +2565,7 @@ >> '*tftp': 'str', >> '*bootfile': 'str', >> '*dhcpstart': 'str', >> + '*nextserver': 'str', > > This is a command addition that libvirt can't take advantage of unless > we get introspection working in a timely manner. It would be a nice addition to libvirt, but is it a problem that libvirt doesn't support all new settings (yet)? Met vriendelijke groet, Bas van Sisseren - -- Bas van Sisseren <bas@quarantainenet.nl> Quarantainenet -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.12 (GNU/Linux) Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/ iEYEARECAAYFAlHSz4sACgkQ19+8tHrpflo3gACgjHd8ApumOrsxN4Wv9nPxsvoJ r6QAnjTKcoxJ6M3q5oZxauNmFsseYw5b =rirP -----END PGP SIGNATURE-----
On 07/02/2013 07:03 AM, Bas van Sisseren wrote: >>> +# @nextserver: #optional IP address of BOOTP server >>> +# > >> Please mark this field as '(since 1.6)'. > > Added in my local checkout. I now have to find out how to generate a new > patch and post it into this thread. I'll try to post a new patch somewhere > in the next days. (I'm new to git :-) ) Feel free to ask questions. Also, see if the wiki page http://wiki.qemu.org/Contribute/SubmitAPatch helps, or could be improved. My typical workflow for amending a series to address review comments is to 'git rebase -i', change the marker on patches I intend to modify from 'pick' to edit' on the screen it pulls up, then exit that editor. From there, git will apply patches in turn, halting on each patch I marked for edit, where I can make the changes, 'git add' them, then 'git rebase --continue' to merge them into the patch series in the right place. Read 'git rebase --help' for a lot more hints on what it can do. >> Does the field work for both IPv4 and IPv6 addresses? > > This setting is IPv4 only. (btw, I think all slirp settings are IPv4 only) Just making sure we are considering things if it matters; but it sounds like it doesn't matter here. >>> # @dns: #optional guest-visible address of the virtual nameserver >>> # >>> # @dnssearch: #optional list of DNS suffixes to search, passed as DHCP option >>> @@ -2563,6 +2565,7 @@ >>> '*tftp': 'str', >>> '*bootfile': 'str', >>> '*dhcpstart': 'str', >>> + '*nextserver': 'str', > >> This is a command addition that libvirt can't take advantage of unless >> we get introspection working in a timely manner. > > It would be a nice addition to libvirt, but is it a problem that libvirt > doesn't support all new settings (yet)? The problem is that libvirt supports multiple versions of qemu, but wants to provide sane error messages to the user. If we add a mapping to libvirt to expose this new parameter, then libvirt would like to know whether the qemu version on the user's machine is new enough to honor that mapping, or old enough to need an upgrade. A version number check is not ideal, because distros like to backport features without bumping the version number (for instance, RHEL 6 ships a qemu that calls itself 0.12.xx, yet behaves like 1.5 for certain features). Creating a new qemu command works (if the command exists or does not exist, libvirt knows the answer without too much effort). Introspection would let libvirt do a query: "what fields does this command support"; and if nextserver is in (or not in) the list, then libvirt knows the answer without too much effort. But introspection is not incorporated yet (we're working on it, and still hopeful it will make 1.6); so that leaves us with only one other option for discovering if an optional parameter is supported - try the command and see if it fails. This is not as friendly, and depending on the command may have other negative side effects from even attempting the command at all. While that's the theory behind QMP additions, there's also the matter that libvirt won't support the new option at all (whether via introspection or try-and-fail probing) unless someone writes a patch for libvirt. On the other hand, the schedule at which libvirt adds support for qemu features shouldn't hold up whether qemu adds the features, since there are more users of qemu than just libvirt.
diff --git a/net/slirp.c b/net/slirp.c index 124e953..f3e239c 100644 --- a/net/slirp.c +++ b/net/slirp.c @@ -136,6 +136,7 @@ static int net_slirp_init(NetClientState *peer, const char *model, const char *vnetwork, const char *vhost, const char *vhostname, const char *tftp_export, const char *bootfile, const char *vdhcp_start, + const char *vnextserver, const char *vnameserver, const char *smb_export, const char *vsmbserver, const char **dnssearch) { @@ -145,6 +146,7 @@ static int net_slirp_init(NetClientState *peer, const char *model, struct in_addr host = { .s_addr = htonl(0x0a000202) }; /* 10.0.2.2 */ 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 in_addr nxtsrv = { .s_addr = 0 }; #ifndef _WIN32 struct in_addr smbsrv = { .s_addr = 0 }; #endif @@ -228,6 +230,10 @@ static int net_slirp_init(NetClientState *peer, const char *model, return -1; } + if (vnextserver && !inet_aton(vnextserver, &nxtsrv)) { + return -1; + } + #ifndef _WIN32 if (vsmbserver && !inet_aton(vsmbserver, &smbsrv)) { return -1; @@ -243,7 +249,7 @@ 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); + tftp_export, bootfile, dhcp, nxtsrv, dns, dnssearch, s); QTAILQ_INSERT_TAIL(&slirp_stacks, s, entry); for (config = slirp_configs; config; config = config->next) { @@ -751,7 +757,7 @@ int net_init_slirp(const NetClientOptions *opts, const char *name, 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->bootfile, user->dhcpstart, user->nextserver, user->dns, user->smb, user->smbserver, dnssearch); while (slirp_configs) { diff --git a/qapi-schema.json b/qapi-schema.json index a80ee40..a8e2c3d 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -2537,6 +2537,8 @@ # @dhcpstart: #optional the first of the 16 IPs the built-in DHCP server can # assign # +# @nextserver: #optional IP address of BOOTP server +# # @dns: #optional guest-visible address of the virtual nameserver # # @dnssearch: #optional list of DNS suffixes to search, passed as DHCP option @@ -2563,6 +2565,7 @@ '*tftp': 'str', '*bootfile': 'str', '*dhcpstart': 'str', + '*nextserver': 'str', '*dns': 'str', '*dnssearch': ['String'], '*smb': 'str', diff --git a/qemu-options.hx b/qemu-options.hx index 8355f9b..8afe42a 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -1350,7 +1350,7 @@ DEF("net", HAS_ARG, QEMU_OPTION_net, #ifdef CONFIG_SLIRP "-net user[,vlan=n][,name=str][,net=addr[/mask]][,host=addr][,restrict=on|off]\n" " [,hostname=host][,dhcpstart=addr][,dns=addr][,dnssearch=domain][,tftp=dir]\n" - " [,bootfile=f][,hostfwd=rule][,guestfwd=rule]" + " [,bootfile=f][,nextserver=addr][,hostfwd=rule][,guestfwd=rule]" #ifndef _WIN32 "[,smb=dir[,smbserver=addr]]\n" #endif @@ -1498,6 +1498,9 @@ When using the user mode network stack, broadcast @var{file} as the BOOTP filename. In conjunction with @option{tftp}, this can be used to network boot a guest from a local directory. +@item nextserver=@var{addr} +Specify the IP address of the TFTP server. + Example (using pxelinux): @example qemu-system-i386 -hda linux.img -boot n -net user,tftp=/path/to/tftp/files,bootfile=/pxelinux.0 diff --git a/slirp/bootp.c b/slirp/bootp.c index b7db9fa..d2e89d6 100644 --- a/slirp/bootp.c +++ b/slirp/bootp.c @@ -227,7 +227,11 @@ static void bootp_reply(Slirp *slirp, const struct bootp_t *bp) memcpy(rbp->bp_hwaddr, bp->bp_hwaddr, ETH_ALEN); rbp->bp_yiaddr = daddr.sin_addr; /* Client IP address */ - rbp->bp_siaddr = saddr.sin_addr; /* Server IP address */ + if (slirp->vnext_server.s_addr == 0) { + rbp->bp_siaddr = saddr.sin_addr; /* Server IP address */ + } else { + rbp->bp_siaddr = slirp->vnext_server; /* Next-Server address */ + } q = rbp->bp_vend; memcpy(q, rfc1533_cookie, 4); diff --git a/slirp/libslirp.h b/slirp/libslirp.h index ceabff8..c3d800b 100644 --- a/slirp/libslirp.h +++ b/slirp/libslirp.h @@ -12,6 +12,7 @@ Slirp *slirp_init(int restricted, struct in_addr vnetwork, struct in_addr vnetmask, struct in_addr vhost, const char *vhostname, const char *tftp_path, const char *bootfile, struct in_addr vdhcp_start, + struct in_addr vnext_server, struct in_addr vnameserver, const char **vdnssearch, void *opaque); void slirp_cleanup(Slirp *slirp); diff --git a/slirp/slirp.c b/slirp/slirp.c index 80b28ea..35f2afd 100644 --- a/slirp/slirp.c +++ b/slirp/slirp.c @@ -200,6 +200,7 @@ Slirp *slirp_init(int restricted, struct in_addr vnetwork, struct in_addr vnetmask, struct in_addr vhost, const char *vhostname, const char *tftp_path, const char *bootfile, struct in_addr vdhcp_start, + struct in_addr vnext_server, struct in_addr vnameserver, const char **vdnssearch, void *opaque) { @@ -225,6 +226,7 @@ Slirp *slirp_init(int restricted, struct in_addr vnetwork, slirp->tftp_prefix = g_strdup(tftp_path); slirp->bootp_filename = g_strdup(bootfile); slirp->vdhcp_startaddr = vdhcp_start; + slirp->vnext_server = vnext_server; slirp->vnameserver_addr = vnameserver; if (vdnssearch) { diff --git a/slirp/slirp.h b/slirp/slirp.h index fe0e65d..a28a8d1 100644 --- a/slirp/slirp.h +++ b/slirp/slirp.h @@ -209,6 +209,7 @@ struct Slirp { struct in_addr vnetwork_mask; struct in_addr vhost_addr; struct in_addr vdhcp_startaddr; + struct in_addr vnext_server; struct in_addr vnameserver_addr; struct in_addr client_ipaddr;
The slirp dhcp-server normally returns its own address as tftp nextserver for netbooting. This patch makes that address configurable, so it is possible to use an external tftp boot- environment. Signed-off-by: Bas van Sisseren <bas@quarantainenet.nl> --- net/slirp.c | 10 ++++++++-- qapi-schema.json | 3 +++ qemu-options.hx | 5 ++++- slirp/bootp.c | 6 +++++- slirp/libslirp.h | 1 + slirp/slirp.c | 2 ++ slirp/slirp.h | 1 + 7 files changed, 24 insertions(+), 4 deletions(-)