Various net and slirp fixes & enhancements
cover Various net and slirp fixes & enhancements
Almost just a reposting of the previously sent series. No patch modified, but a nifty (IMO) new one: ping forwarding for slirp using the unprivileged ICMP sockets of Linux 3.0. See commit log for a simple how-to.
Jan Kiszka (10):
slirp: Fix restricted mode
slirp: Canonicalize restrict syntax
slirp: Strictly associate DHCP/BOOTP and TFTP with virtual host
slirp: Replace m_freem with m_free
slirp: Put forked exec into separate process group
slirp: Forward ICMP echo requests via unprivileged sockets
net: Improve layout of 'info network'
net: Refactor net_client_types
net: Dump client type 'info network'
net: Consistently use qemu_macaddr_default_if_unset
hw/dp8393x.c | 2 +- hw/etraxfs_eth.c | 2 +- hw/mcf_fec.c | 2 +- hw/mipsnet.c | 2 +- hw/qdev.c | 2 +- hw/stellaris.c | 2 +- hw/xen_devconfig.c | 4 +- net.c | 65 +++++++++++++++++++++-------------- net.h | 8 +++-- net/slirp.c | 23 +++++++++---- qemu-options.hx | 4 +- slirp/ip_icmp.c | 95 +++++++++++++++++++++++++++++++++++++++++++++++++-- slirp/ip_icmp.h | 3 ++ slirp/ip_input.c | 30 +++-------------- slirp/ip_output.c | 4 +- slirp/mbuf.h | 3 -- slirp/misc.c | 16 ++++++++- slirp/slirp.c | 37 ++++++++++++++++++++ slirp/slirp.h | 5 +++ slirp/socket.c | 2 + slirp/tcp_input.c | 10 +++--- slirp/tcp_subr.c | 2 +- slirp/udp.c | 23 +++++++----- 23 files changed, 249 insertions(+), 97 deletions(-)
Signature · 1 line
1.7.3.4
PATCH 1/10 slirp: Fix restricted mode
This aligns the code to what the documentation claims: Allow everything but requests that would have to be routed outside of the virtual LAN.
So we need to drop the unneeded IP-level filter, allow TFTP requests, and add the missing protocol-level filter to ICMP.
--- slirp/ip_icmp.c | 2 ++ slirp/ip_input.c | 21 --------------------- slirp/udp.c | 8 ++++---- 3 files changed, 6 insertions(+), 25 deletions(-)
slirp/ip_icmp.c +2 -0
@@ -101,6 +101,8 @@ icmp_input(struct mbuf *m, int hlen) ip->ip_len += hlen;/* since ip_input subtracts this */ if (ip->ip_dst.s_addr == slirp->vhost_addr.s_addr) {icmp_reflect (m); + }else if (slirp->restricted) { + goto freeit; }else {struct socket *so;struct sockaddr_in addr;
slirp/ip_input.c +0 -21
@@ -118,27 +118,6 @@ ip_input(struct mbuf *m) goto bad; } -if (slirp->restricted) { -if ((ip->ip_dst.s_addr & slirp->vnetwork_mask.s_addr) == - slirp->vnetwork_addr.s_addr) { -if (ip->ip_dst.s_addr ==0xffffffff && ip->ip_p !=IPPROTO_UDP ) - goto bad; - }else { -uint32_t inv_mask = ~slirp->vnetwork_mask.s_addr; -struct ex_list *ex_ptr; - -if ((ip->ip_dst.s_addr & inv_mask) == inv_mask) { - goto bad; - } -for (ex_ptr = slirp->exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) -if (ex_ptr->ex_addr.s_addr == ip->ip_dst.s_addr) -break ; - -if (!ex_ptr) - goto bad; - } - } -/* Should drop packet if mbuf too long? hmmm... */ if (m->m_len > ip->ip_len)m_adj (m, ip->ip_len - m->m_len);
slirp/udp.c +4 -4
@@ -125,10 +125,6 @@ udp_input(register struct mbuf *m, int iphlen) goto bad; } -if (slirp->restricted) { - goto bad; - } -/* * handle TFTP */
@@ -137,6 +133,10 @@ udp_input(register struct mbuf *m, int iphlen) goto bad; } +if (slirp->restricted) { + goto bad; + } +/* * Locate pcb for datagram. */
Signature · 1 line
1.7.3.4
PATCH 2/10 slirp: Canonicalize restrict syntax
In reply to Jan KiszkaAll other boolean arguments accept on|off - except for slirp's restrict. Fix that while still accepting the formerly allowed yes|y|no|n, but reject everything else. This avoids accidentally allowing external connections because syntax errors were so far interpreted as 'restrict=no'.
--- net/slirp.c | 21 +++++++++++++++------ qemu-options.hx | 4 ++-- 2 files changed, 17 insertions(+), 8 deletions(-)
net/slirp.c +15 -6
@@ -240,7 +240,8 @@ static int net_slirp_init(VLANState *vlan, const char *model, nc =qemu_new_net_client (&net_slirp_info, vlan,NULL , model, name);snprintf (nc->info_str,sizeof (nc->info_str), -"net=%s, restricted=%c" ,inet_ntoa (net), restricted ?'y' :'n' ); +"net=%s,restrict=%s" ,inet_ntoa (net), + restricted ?"on" :"off" ); s =DO_UPCAST (SlirpState, nc, nc);
@@ -689,6 +690,7 @@ int net_init_slirp(QemuOpts *opts,const char *bootfile;const char *smb_export;const char *vsmbsrv; +const char *restrict_opt;char *vnet =NULL ;int restricted =0 ;int ret;
@@ -702,6 +704,18 @@ int net_init_slirp(QemuOpts *opts, smb_export =qemu_opt_get (opts,"smb" ); vsmbsrv =qemu_opt_get (opts,"smbserver" ); + restrict_opt =qemu_opt_get (opts,"restrict" ); +if (restrict_opt) { +if (!strcmp (restrict_opt,"on" ) || + !strcmp (restrict_opt,"yes" ) || !strcmp (restrict_opt,"y" )) { + restricted =1 ; + }else if (strcmp (restrict_opt,"off" ) && +strcmp (restrict_opt,"no" ) &&strcmp (restrict_opt,"n" )) { +error_report ("invalid option: 'restrict=%s'" , restrict_opt); +return -1 ; + } + } +if (qemu_opt_get (opts,"ip" )) {const char *ip =qemu_opt_get (opts,"ip" );int l =strlen (ip) +strlen ("/24" ) +1 ;
@@ -720,11 +734,6 @@ int net_init_slirp(QemuOpts *opts, vnet =qemu_strdup (qemu_opt_get (opts,"net" )); } -if (qemu_opt_get (opts,"restrict" ) && -qemu_opt_get (opts,"restrict" )[0 ] =='y' ) { - restricted =1 ; - } -qemu_opt_foreach (opts, net_init_slirp_configs,NULL ,0 ); ret = net_slirp_init(vlan, "user", name, restricted, vnet, vhost,
qemu-options.hx +2 -2
@@ -1092,7 +1092,7 @@ DEF("net", HAS_ARG, QEMU_OPTION_net, "-net nic[,vlan=n][,macaddr=mac][,model=type][,name=str][,addr=str][,vectors=v]\n" " create a new Network Interface Card and connect it to VLAN 'n'\n" #ifdef CONFIG_SLIRP - "-net user[,vlan=n][,name=str][,net=addr[/mask]][,host=addr][,restrict=y|n]\n" + "-net user[,vlan=n][,name=str][,net=addr[/mask]][,host=addr][,restrict=on|off]\n" " [,hostname=host][,dhcpstart=addr][,dns=addr][,tftp=dir][,bootfile=f]\n" " [,hostfwd=rule][,guestfwd=rule]" #ifndef _WIN32
@@ -1185,7 +1185,7 @@ 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 restrict=y|yes|n|no +@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 to the outside. This option does not affect any explicitly set forwarding rules.
Signature · 1 line
1.7.3.4
PATCH 3/10 slirp: Strictly associate DHCP/BOOTP and TFTP with virtual host
In reply to Jan KiszkaInstead of accepting every DHCP/BOOTP and TFTP packet, only invoke the built-in servers if the target is the virtual host.
--- slirp/udp.c | 13 ++++++++----- 1 files changed, 8 insertions(+), 5 deletions(-)
slirp/udp.c +8 -5
@@ -120,15 +120,18 @@ udp_input(register struct mbuf *m, int iphlen)/* * handle DHCP/BOOTP */ -if (ntohs (uh->uh_dport) ==BOOTP_SERVER ) { -bootp_input (m); - goto bad; - } +if (ntohs (uh->uh_dport) ==BOOTP_SERVER && + (ip->ip_dst.s_addr == slirp->vhost_addr.s_addr || + ip->ip_dst.s_addr ==0xffffffff )) { +bootp_input (m); + goto bad; + }/* * handle TFTP */ -if (ntohs (uh->uh_dport) ==TFTP_SERVER ) { +if (ntohs (uh->uh_dport) ==TFTP_SERVER && + ip->ip_dst.s_addr == slirp->vhost_addr.s_addr) {tftp_input (m); goto bad; }
Signature · 1 line
1.7.3.4
PATCH 4/10 slirp: Replace m_freem with m_free
In reply to Jan KiszkaRemove this pointless wrapping.
--- slirp/ip_icmp.c | 6 +++--- slirp/ip_input.c | 8 ++++---- slirp/ip_output.c | 4 ++-- slirp/mbuf.h | 3 --- slirp/tcp_input.c | 10 +++++----- slirp/tcp_subr.c | 2 +- slirp/udp.c | 2 +- 7 files changed, 16 insertions(+), 19 deletions(-)
slirp/ip_icmp.c +3 -3
@@ -81,7 +81,7 @@ icmp_input(struct mbuf *m, int hlen)*/ if (icmplen <ICMP_MINLEN ) {/* min 8 bytes payload */ freeit: -m_freem (m); +m_free (m); goto end_error; }
@@ -155,11 +155,11 @@ icmp_input(struct mbuf *m, int hlen)case ICMP_TSTAMP :case ICMP_MASKREQ :case ICMP_REDIRECT : -m_freem (m); +m_free (m);break ;default : -m_freem (m); +m_free (m); }/* swith */ end_error:
slirp/ip_input.c +4 -4
@@ -204,7 +204,7 @@ ip_input(struct mbuf *m) }return ; bad: -m_freem (m); +m_free (m);return ; }
@@ -297,7 +297,7 @@ ip_reass(Slirp *slirp, struct ip *ip, struct ipq *fp)break ; } q = q->ipf_next; -m_freem (dtom (slirp, q->ipf_prev)); +m_free (dtom (slirp, q->ipf_prev));ip_deq (q->ipf_prev); }
@@ -363,7 +363,7 @@ insert:return ip; dropfrag: -m_freem (m); +m_free (m);return NULL ; }
@@ -379,7 +379,7 @@ ip_freef(Slirp *slirp, struct ipq *fp)for (q = fp->frag_link.next; q != (struct ipasfrag *)&fp->frag_link; q = p) { p = q->ipf_next;ip_deq (q); -m_freem (dtom (slirp, q)); +m_free (dtom (slirp, q)); }remque (&fp->ip_link); (void )m_free (dtom (slirp, fp));
slirp/ip_output.c +2 -2
@@ -159,7 +159,7 @@ sendorfree:if (error ==0 )if_output (so, m);else -m_freem (m); +m_free (m); } }
@@ -167,6 +167,6 @@ done:return (error); bad: -m_freem (m0); +m_free (m0); goto done; }
slirp/mbuf.h +0 -3
@@ -33,9 +33,6 @@#ifndef _MBUF_H_#define _MBUF_H_ -#define m_freem m_free - -#define MINCSIZE 4096/* Amount to increase mbuf if too small */ /*
slirp/tcp_input.c +5 -5
@@ -136,7 +136,7 @@ tcp_reass(register struct tcpcb *tp, register struct tcpiphdr *ti, i = q->ti_seq + q->ti_len - ti->ti_seq;if (i >0 ) {if (i >= ti->ti_len) { -m_freem (m); +m_free (m);/* * Try to present any queued data * at the left window edge to the user.
@@ -170,7 +170,7 @@ tcp_reass(register struct tcpcb *tp, register struct tcpiphdr *ti, q =tcpiphdr_next (q); m =tcpiphdr_prev (q)->ti_mbuf;remque (tcpiphdr2qlink (tcpiphdr_prev (q))); -m_freem (m); +m_free (m); }/*
@@ -197,7 +197,7 @@ present: m = ti->ti_mbuf; ti =tcpiphdr_next (ti);if (so->so_state &SS_FCANTSENDMORE ) -m_freem (m); +m_free (m);else {if (so->so_emu) {if (tcp_emu (so,m))sbappend (so, m);
@@ -451,7 +451,7 @@ findso: acked = ti->ti_ack - tp->snd_una;sbdrop (&so->so_snd, acked); tp->snd_una = ti->ti_ack; -m_freem (m); +m_free (m);/* * If all outstanding data are acked, stop
@@ -1260,7 +1260,7 @@ dropafterack:*/ if (tiflags &TH_RST ) goto drop; -m_freem (m); +m_free (m); tp->t_flags |=TF_ACKNOW ; (void )tcp_output (tp);return ;
slirp/tcp_subr.c +1 -1
@@ -250,7 +250,7 @@ tcp_close(struct tcpcb *tp) t =tcpiphdr_next (t); m =tcpiphdr_prev (t)->ti_mbuf;remque (tcpiphdr2qlink (tcpiphdr_prev (t))); -m_freem (m); +m_free (m); }free (tp); so->so_tcpcb =NULL ;
slirp/udp.c +1 -1
@@ -222,7 +222,7 @@ udp_input(register struct mbuf *m, int iphlen)return ; bad: -m_freem (m); +m_free (m);return ; }
Signature · 1 line
1.7.3.4
PATCH 5/10 slirp: Put forked exec into separate process group
In reply to Jan KiszkaRecent smb daemons tend to terminate themselves via a process group SIGTERM. If the daemon is still in qemu's group by that time, qemu will die as well. Avoid this by always pushing fork_exec processes into a group of their own, not just (unused) type 2 execs.
--- slirp/misc.c | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-)
slirp/misc.c +2 -1
@@ -153,11 +153,12 @@ fork_exec(struct socket *so, const char *ex, int do_pty)return 0 ;case 0 : +setsid (); +/* Set the DISPLAY */ if (do_pty ==2 ) { (void )close (master);#ifdef TIOCSCTTY /* XXXXX */ - (void )setsid ();ioctl (s,TIOCSCTTY , (char *)NULL );#endif }else {
Signature · 1 line
1.7.3.4
PATCH 6/10 slirp: Forward ICMP echo requests via unprivileged sockets
In reply to Jan KiszkaLinux 3.0 gained support for unprivileged ICMP ping sockets. Use this feature to forward guest pings to the outer world. The host admin has to set the ping_group_range in order to grant access to those sockets. To allow ping for the users group (GID 100):
echo 100 100 > /proc/sys/net/ipv4/ping_group_range
--- slirp/ip_icmp.c | 87 +++++++++++++++++++++++++++++++++++++++++++++++++++++- slirp/ip_icmp.h | 3 ++ slirp/ip_input.c | 1 + slirp/misc.c | 13 ++++++++ slirp/slirp.c | 37 +++++++++++++++++++++++ slirp/slirp.h | 5 +++ slirp/socket.c | 2 + 7 files changed, 147 insertions(+), 1 deletions(-)
slirp/ip_icmp.c +86 -1
@@ -60,6 +60,52 @@ static const int icmp_flush[19] = { /* ADDR MASK REPLY (18) */ 0 }; +void icmp_init (Slirp *slirp) +{ + slirp->icmp.so_next = slirp->icmp.so_prev = &slirp->icmp; + slirp->icmp_last_so = &slirp->icmp; +} + +static int icmp_send (struct socket *so,struct mbuf *m,int hlen) +{ + struct ip *ip = mtod(m, struct ip *); +struct sockaddr_in addr; + + so->s =qemu_socket (AF_INET ,SOCK_DGRAM ,IPPROTO_ICMP ); +if (so->s ==-1 ) { +return -1 ; + } + + so->so_m = m; + so->so_faddr = ip->ip_dst; + so->so_laddr = ip->ip_src; + so->so_iptos = ip->ip_tos; + so->so_type =IPPROTO_ICMP ; + so->so_state =SS_ISFCONNECTED ; + so->so_expire = curtime +SO_EXPIRE ; + + addr.sin_family =AF_INET ; + addr.sin_addr = so->so_faddr; + +insque (so, &so->slirp->icmp); + +if (sendto (so->s, m->m_data + hlen, m->m_len - hlen,0 , + (struct sockaddr *)&addr,sizeof (addr)) ==-1 ) { +DEBUG_MISC ((dfd,"icmp_input icmp sendto tx errno = %d-%s\n" , + errno,strerror (errno))); +icmp_error (m,ICMP_UNREACH ,ICMP_UNREACH_NET ,0 ,strerror (errno)); +icmp_detach (so); + } + +return 0 ; +} + +void icmp_detach (struct socket *so) +{ +closesocket (so->s); +sofree (so); +} +/* * Process a received ICMP message. */
@@ -97,7 +143,6 @@ icmp_input(struct mbuf *m, int hlen)DEBUG_ARG ("icmp_type = %d" , icp->icmp_type);switch (icp->icmp_type) {case ICMP_ECHO : - icp->icmp_type =ICMP_ECHOREPLY ; ip->ip_len += hlen;/* since ip_input subtracts this */ if (ip->ip_dst.s_addr == slirp->vhost_addr.s_addr) {icmp_reflect (m);
@@ -107,6 +152,9 @@ icmp_input(struct mbuf *m, int hlen)struct socket *so;struct sockaddr_in addr;if ((so =socreate (slirp)) ==NULL ) goto freeit; +if (icmp_send (so, m, hlen) ==0 ) { +return ; + }if (udp_attach (so) ==-1 ) {DEBUG_MISC ((dfd,"icmp_input udp_attach errno = %d-%s\n" , errno,strerror (errno)));
@@ -321,6 +369,7 @@ icmp_reflect(struct mbuf *m) m->m_len -= hlen; icp = mtod(m, struct icmp *); + icp->icmp_type =ICMP_ECHOREPLY ; icp->icmp_cksum =0 ; icp->icmp_cksum =cksum (m, ip->ip_len - hlen);
@@ -351,3 +400,39 @@ icmp_reflect(struct mbuf *m) (void )ip_output ((struct socket *)NULL , m); } + +void icmp_receive (struct socket *so) +{ +struct mbuf *m = so->so_m; + struct ip *ip = mtod(m, struct ip *); +int hlen = ip->ip_hl <<2 ; +u_char error_code; +struct icmp *icp; +int id, len; + + m->m_data += hlen; + m->m_len -= hlen; + icp = mtod(m, struct icmp *); + + id = icp->icmp_id; + len =recv (so->s, icp, m->m_len,0 ); + icp->icmp_id = id; + + m->m_data -= hlen; + m->m_len += hlen; + +if (len ==-1 || len ==0 ) { +if (errno ==ENETUNREACH ) { + error_code =ICMP_UNREACH_NET ; + }else { + error_code =ICMP_UNREACH_HOST ; + } +DEBUG_MISC ((dfd," udp icmp rx errno = %d-%s\n" , errno, +strerror (errno))); +icmp_error (so->so_m,ICMP_UNREACH , error_code,0 ,strerror (errno)); + }else { +icmp_reflect (so->so_m); + so->so_m =NULL ;/* Don't m_free() it again! */ + } +icmp_detach (so); +}
slirp/ip_icmp.h +3 -0
@@ -153,9 +153,12 @@ struct icmp { (type) == ICMP_IREQ || (type) == ICMP_IREQREPLY || \ (type) == ICMP_MASKREQ || (type) == ICMP_MASKREPLY) +void icmp_init (Slirp *slirp);void icmp_input (struct mbuf *,int );void icmp_error (struct mbuf *msrc,u_char type,u_char code,int minsize,const char *message);void icmp_reflect (struct mbuf *); +void icmp_receive (struct socket *so); +void icmp_detach (struct socket *so);#endif
slirp/ip_input.c +1 -0
@@ -58,6 +58,7 @@ ip_init(Slirp *slirp) slirp->ipq.ip_link.next = slirp->ipq.ip_link.prev = &slirp->ipq.ip_link;udp_init (slirp);tcp_init (slirp); +icmp_init (slirp); }/*
slirp/misc.c +13 -0
@@ -407,4 +407,17 @@ void slirp_connection_info(Slirp *slirp, Monitor *mon)inet_ntoa (dst_addr),ntohs (dst_port), so->so_rcv.sb_cc, so->so_snd.sb_cc); } + +for (so = slirp->icmp.so_next; so != &slirp->icmp; so = so->so_next) { + n =snprintf (buf,sizeof (buf)," ICMP[%d sec]" , + (so->so_expire - curtime) /1000 ); + src.sin_addr = so->so_laddr; + dst_addr = so->so_faddr; +memset (&buf[n],' ' ,19 - n); + buf[19 ] =0 ; +monitor_printf (mon,"%s %3d %15s - " , buf, so->s, + src.sin_addr.s_addr ?inet_ntoa (src.sin_addr) :"*" ); +monitor_printf (mon,"%15s - %5d %5d\n" ,inet_ntoa (dst_addr), + so->so_rcv.sb_cc, so->so_snd.sb_cc); + } }
slirp/slirp.c +37 -0
@@ -373,6 +373,31 @@ void slirp_select_fill(int *pnfds,UPD_NFDS (so->s); } } + +/* +* ICMP sockets +*/ +for (so = slirp->icmp.so_next; so != &slirp->icmp; + so = so_next) { + so_next = so->so_next; + +/* +* See if it's timed out +*/ +if (so->so_expire) { +if (so->so_expire <= curtime) { +icmp_detach (so); +continue ; + }else { + do_slowtimo =1 ;/* Let socket expire */ + } + } + +if (so->so_state &SS_ISFCONNECTED ) { +FD_SET (so->s, readfds); +UPD_NFDS (so->s); + } + } } *pnfds = nfds;
@@ -542,6 +567,18 @@ void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds,sorecvfrom (so); } } + +/* +* Check incoming ICMP relies. +*/ +for (so = slirp->icmp.so_next; so != &slirp->icmp; + so = so_next) { + so_next = so->so_next; + +if (so->s !=-1 &&FD_ISSET (so->s, readfds)) { +icmp_receive (so); + } + } }/*
slirp/slirp.h +5 -0
@@ -152,6 +152,7 @@ int inet_aton(const char *cp, struct in_addr *ia);#include "tcp_var.h" #include "tcpip.h" #include "udp.h" +#include "ip_icmp.h" #include "mbuf.h" #include "sbuf.h" #include "socket.h"
@@ -218,6 +219,10 @@ struct Slirp {struct socket udb;struct socket *udp_last_so; +/* icmp states */ +struct socket icmp; +struct socket *icmp_last_so; +/* tftp states */ char *tftp_prefix;struct tftp_session tftp_sessions[TFTP_SESSIONS_MAX ];
slirp/socket.c +2 -0
@@ -71,6 +71,8 @@ sofree(struct socket *so) slirp->tcp_last_so = &slirp->tcb; }else if (so == slirp->udp_last_so) { slirp->udp_last_so = &slirp->udb; + }else if (so == slirp->icmp_last_so) { + slirp->icmp_last_so = &slirp->icmp; }m_free (so->so_m);
Signature · 1 line
1.7.3.4
PATCH 7/10 net: Improve layout of 'info network'
In reply to Jan KiszkaImprove the layout when listing non-vlan clients via 'info network'. The result looks like this:
(qemu) info network
Devices not on any VLAN:
orphan: net=10.0.2.0, restricted=n
virtio-net-pci.0: model=virtio-net-pci,macaddr=52:54:00:12:34:56
\ network2: fd=5
e1000.0: model=e1000,macaddr=52:54:00:12:34:57
\ network1: net=10.0.2.0, restricted=n
rtl8139.0: model=rtl8139,macaddr=52:54:00:12:34:58
ie. peers are grouped, orphans are listed as before.
--- net.c | 14 +++++++++----- 1 files changed, 9 insertions(+), 5 deletions(-)
net.c +9 -5
@@ -1224,7 +1224,8 @@ int do_netdev_del(Monitor *mon, const QDict *qdict, QObject **ret_data)void do_info_network (Monitor *mon) {VLANState *vlan; -VLANClientState *vc; +VLANClientState *vc, *peer; +net_client_type type; QTAILQ_FOREACH(vlan, &vlans, next) {monitor_printf (mon,"VLAN %d devices:\n" , vlan->id);
@@ -1235,11 +1236,14 @@ void do_info_network(Monitor *mon) }monitor_printf (mon,"Devices not on any VLAN:\n" ); QTAILQ_FOREACH(vc, &non_vlan_clients, next) { -monitor_printf (mon," %s: %s" , vc->name, vc->info_str); -if (vc->peer) { -monitor_printf (mon," peer=%s" , vc->peer->name); + peer = vc->peer; + type = vc->info->type; +if (!peer || type ==NET_CLIENT_TYPE_NIC ) { +monitor_printf (mon," %s: %s\n" , vc->name, vc->info_str); + }/* else it's a netdev connected to a NIC, printed with the NIC */ +if (peer && type ==NET_CLIENT_TYPE_NIC ) { +monitor_printf (mon," \\ %s: %s\n" , peer->name, peer->info_str); } -monitor_printf (mon,"\n" ); } }
Signature · 1 line
1.7.3.4
PATCH 8/10 net: Refactor net_client_types
In reply to Jan KiszkaPosition entries of net_client_types according to the corresponding values of NET_CLIENT_TYPE_*. The array size is now defined by NET_CLIENT_TYPE_MAX. This will allow to obtain entries based on type value in later patches.
At this chance rename NET_CLIENT_TYPE_SLIRP to NET_CLIENT_TYPE_USER for the sake of consistency.
--- net.c | 30 ++++++++++++++++++------------ net.h | 6 ++++-- net/slirp.c | 2 +- 3 files changed, 23 insertions(+), 15 deletions(-)
net.c +18 -12
@@ -830,14 +830,15 @@ static const struct {const char *type;net_client_init_func init;QemuOptDesc desc[NET_MAX_DESC ]; -} net_client_types[] = { - { +} net_client_types[NET_CLIENT_TYPE_MAX] = { + [NET_CLIENT_TYPE_NONE] = { .type = "none", .desc = { NET_COMMON_PARAMS_DESC, {/* end of list */ } }, - }, { + }, + [NET_CLIENT_TYPE_NIC] = { .type = "nic", .init = net_init_nic, .desc = {
@@ -866,8 +867,9 @@ static const struct { }, {/* end of list */ } }, + }, #ifdef CONFIG_SLIRP - }, { + [NET_CLIENT_TYPE_USER] = { .type = "user", .init = net_init_slirp, .desc = {
@@ -927,8 +929,9 @@ static const struct { }, {/* end of list */ } }, + }, #endif - }, { + [NET_CLIENT_TYPE_TAP] = { .type = "tap", .init = net_init_tap, .desc = {
@@ -975,7 +978,8 @@ static const struct {#endif /* _WIN32 */ {/* end of list */ } }, - }, { + }, + [NET_CLIENT_TYPE_SOCKET] = { .type = "socket", .init = net_init_socket, .desc = {
@@ -1003,8 +1007,9 @@ static const struct { }, {/* end of list */ } }, + }, #ifdef CONFIG_VDE - }, { + [NET_CLIENT_TYPE_VDE] = { .type = "vde", .init = net_init_vde, .desc = {
@@ -1028,8 +1033,9 @@ static const struct { }, {/* end of list */ } }, + }, #endif - }, { + [NET_CLIENT_TYPE_DUMP] = { .type = "dump", .init = net_init_dump, .desc = {
@@ -1046,7 +1052,6 @@ static const struct { {/* end of list */ } }, }, - {/* end of list */ } };int net_client_init (Monitor *mon,QemuOpts *opts,int is_netdev)
@@ -1094,8 +1099,9 @@ int net_client_init(Monitor *mon, QemuOpts *opts, int is_netdev) name =qemu_opt_get (opts,"name" ); } -for (i =0 ; net_client_types[i].type !=NULL ; i++) { -if (!strcmp (net_client_types[i].type, type)) { +for (i =0 ; i <NET_CLIENT_TYPE_MAX ; i++) { +if (net_client_types[i].type !=NULL && + !strcmp (net_client_types[i].type, type)) {VLANState *vlan =NULL ;int ret;
@@ -1330,7 +1336,7 @@ void net_check_clients(void)case NET_CLIENT_TYPE_NIC : has_nic =1 ;break ; -case NET_CLIENT_TYPE_SLIRP : +case NET_CLIENT_TYPE_USER :case NET_CLIENT_TYPE_TAP :case NET_CLIENT_TYPE_SOCKET :case NET_CLIENT_TYPE_VDE :
net.h +4 -2
@@ -31,11 +31,13 @@ typedef struct NICConf {typedef enum {NET_CLIENT_TYPE_NONE ,NET_CLIENT_TYPE_NIC , -NET_CLIENT_TYPE_SLIRP , +NET_CLIENT_TYPE_USER ,NET_CLIENT_TYPE_TAP ,NET_CLIENT_TYPE_SOCKET ,NET_CLIENT_TYPE_VDE , -NET_CLIENT_TYPE_DUMP +NET_CLIENT_TYPE_DUMP , + +NET_CLIENT_TYPE_MAX }net_client_type ;typedef void (NetPoll )(VLANClientState *,bool enable);
net/slirp.c +1 -1
@@ -128,7 +128,7 @@ static void net_slirp_cleanup(VLANClientState *nc) }static NetClientInfo net_slirp_info = { - .type =NET_CLIENT_TYPE_SLIRP , + .type =NET_CLIENT_TYPE_USER , .size =sizeof (SlirpState), .receive = net_slirp_receive, .cleanup = net_slirp_cleanup,
Signature · 1 line
1.7.3.4
PATCH 9/10 net: Dump client type 'info network'
In reply to Jan KiszkaInclude the client type name into the output of 'info network'. The result looks like this:
(qemu) info network
VLAN 0 devices:
rtl8139.0: type=nic,model=rtl8139,macaddr=52:54:00:12:34:57
Devices not on any VLAN:
virtio-net-pci.0: type=nic,model=virtio-net-pci,macaddr=52:54:00:12:34:56
\ network1: type=tap,fd=5
--- net.c | 15 ++++++++++++--- 1 files changed, 12 insertions(+), 3 deletions(-)
net.c +12 -3
@@ -1227,6 +1227,12 @@ int do_netdev_del(Monitor *mon, const QDict *qdict, QObject **ret_data)return 0 ; } +static void print_net_client (Monitor *mon,VLANClientState *vc) +{ +monitor_printf (mon,"%s: type=%s,%s\n" , vc->name, + net_client_types[vc->info->type].type, vc->info_str); +} +void do_info_network (Monitor *mon) {VLANState *vlan;
@@ -1237,7 +1243,8 @@ void do_info_network(Monitor *mon)monitor_printf (mon,"VLAN %d devices:\n" , vlan->id); QTAILQ_FOREACH(vc, &vlan->clients, next) { -monitor_printf (mon," %s: %s\n" , vc->name, vc->info_str); +monitor_printf (mon," " ); +print_net_client (mon, vc); } }monitor_printf (mon,"Devices not on any VLAN:\n" );
@@ -1245,10 +1252,12 @@ void do_info_network(Monitor *mon) peer = vc->peer; type = vc->info->type;if (!peer || type ==NET_CLIENT_TYPE_NIC ) { -monitor_printf (mon," %s: %s\n" , vc->name, vc->info_str); +monitor_printf (mon," " ); +print_net_client (mon, vc); }/* else it's a netdev connected to a NIC, printed with the NIC */ if (peer && type ==NET_CLIENT_TYPE_NIC ) { -monitor_printf (mon," \\ %s: %s\n" , peer->name, peer->info_str); +monitor_printf (mon," \\ " ); +print_net_client (mon, peer); } } }
Signature · 1 line
1.7.3.4
PATCH 10/10 net: Consistently use qemu_macaddr_default_if_unset
In reply to Jan KiszkaDrop the open-coded MAC assignment from net_init_nic and replace it with standard qemu_macaddr_default_if_unset which is also used by qdev. That avoid creating colliding MACs when instantiating NICs via different mechanisms.
This change requires to store the MAC as MACAddr in NICInfo, and the remaining nd_table users need to be updated.
Based on suggestion by Peter Maydell.
--- hw/dp8393x.c | 2 +- hw/etraxfs_eth.c | 2 +- hw/mcf_fec.c | 2 +- hw/mipsnet.c | 2 +- hw/qdev.c | 2 +- hw/stellaris.c | 2 +- hw/xen_devconfig.c | 4 ++-- net.c | 10 ++-------- net.h | 2 +- 9 files changed, 11 insertions(+), 17 deletions(-)
hw/dp8393x.c +1 -1
@@ -898,7 +898,7 @@ void dp83932_init(NICInfo *nd, target_phys_addr_t base, int it_shift, s->watchdog =qemu_new_timer_ns (vm_clock, dp8393x_watchdog, s); s->regs[SONIC_SR ] =0x0004 ;/* only revision recognized by Linux */ -memcpy (s->conf.macaddr.a, nd->macaddr,sizeof (s->conf.macaddr)); + s->conf.macaddr = nd->macaddr; s->conf.vlan = nd->vlan; s->conf.peer = nd->netdev;
hw/etraxfs_eth.c +1 -1
@@ -602,7 +602,7 @@ void *etraxfs_eth_init(NICInfo *nd, target_phys_addr_t base, int phyaddr) DEVICE_NATIVE_ENDIAN);cpu_register_physical_memory (base,0x5c , eth->ethregs); -memcpy (eth->conf.macaddr.a, nd->macaddr,sizeof (nd->macaddr)); + eth->conf.macaddr = nd->macaddr; eth->conf.vlan = nd->vlan; eth->conf.peer = nd->netdev;
hw/mcf_fec.c +1 -1
@@ -471,7 +471,7 @@ void mcf_fec_init(NICInfo *nd, target_phys_addr_t base, qemu_irq *irq) DEVICE_NATIVE_ENDIAN);cpu_register_physical_memory (base,0x400 , s->mmio_index); -memcpy (s->conf.macaddr.a, nd->macaddr,sizeof (nd->macaddr)); + s->conf.macaddr = nd->macaddr; s->conf.vlan = nd->vlan; s->conf.peer = nd->netdev;
hw/mipsnet.c +1 -1
@@ -258,7 +258,7 @@ void mipsnet_init (int base, qemu_irq irq, NICInfo *nd) s->irq = irq;if (nd) { -memcpy (s->conf.macaddr.a, nd->macaddr,sizeof (nd->macaddr)); + s->conf.macaddr = nd->macaddr; s->conf.vlan = nd->vlan; s->conf.peer = nd->netdev;
hw/qdev.c +1 -1
@@ -459,7 +459,7 @@ void qdev_connect_gpio_out(DeviceState * dev, int n, qemu_irq pin)void qdev_set_nic_properties (DeviceState *dev,NICInfo *nd) { -qdev_prop_set_macaddr (dev,"mac" , nd->macaddr); +qdev_prop_set_macaddr (dev,"mac" , nd->macaddr.a);if (nd->vlan)qdev_prop_set_vlan (dev,"vlan" , nd->vlan);if (nd->netdev)
hw/stellaris.c +1 -1
@@ -1230,7 +1230,7 @@ static void stellaris_init(const char *kernel_filename, const char *cpu_model, } } -stellaris_sys_init (0x400fe000 , pic[28 ], board, nd_table[0 ].macaddr); +stellaris_sys_init (0x400fe000 , pic[28 ], board, nd_table[0 ].macaddr.a);for (i =0 ; i <7 ; i++) {if (board->dc4 & (1 << i)) {
hw/xen_devconfig.c +2 -2
@@ -126,8 +126,8 @@ int xen_config_dev_nic(NICInfo *nic)char mac[20 ];snprintf (mac,sizeof (mac),"%02x:%02x:%02x:%02x:%02x:%02x" , - nic->macaddr[0 ], nic->macaddr[1 ], nic->macaddr[2 ], - nic->macaddr[3 ], nic->macaddr[4 ], nic->macaddr[5 ]); + nic->macaddr.a[0 ], nic->macaddr.a[1 ], nic->macaddr.a[2 ], + nic->macaddr.a[3 ], nic->macaddr.a[4 ], nic->macaddr.a[5 ]);xen_be_printf (NULL ,1 ,"config nic %d: mac=\"%s\"\n" , nic->vlan->id, mac);xen_config_dev_dirs ("vif" ,"qnic" , nic->vlan->id, fe, be,sizeof (fe));
net.c +2 -8
@@ -776,18 +776,12 @@ static int net_init_nic(QemuOpts *opts, nd->devaddr =qemu_strdup (qemu_opt_get (opts,"addr" )); } - nd->macaddr[0 ] =0x52 ; - nd->macaddr[1 ] =0x54 ; - nd->macaddr[2 ] =0x00 ; - nd->macaddr[3 ] =0x12 ; - nd->macaddr[4 ] =0x34 ; - nd->macaddr[5 ] =0x56 + idx; -if (qemu_opt_get (opts,"macaddr" ) && -net_parse_macaddr (nd->macaddr,qemu_opt_get (opts,"macaddr" )) <0 ) { +net_parse_macaddr (nd->macaddr.a,qemu_opt_get (opts,"macaddr" )) <0 ) {error_report ("invalid syntax for ethernet address" );return -1 ; } +qemu_macaddr_default_if_unset (&nd->macaddr); nd->nvectors =qemu_opt_get_number (opts,"vectors" ,DEV_NVECTORS_UNSPECIFIED );
net.h +1 -1
@@ -129,7 +129,7 @@ int do_set_link(Monitor *mon, const QDict *qdict, QObject **ret_data);#define MAX_NICS 8struct NICInfo { -uint8_t macaddr[6 ]; +MACAddr macaddr;char *model;char *name;char *devaddr;
Signature · 1 line
1.7.3.4
Quoted 4 lines · Jan Kiszka
Almost just a reposting of the previously sent series. No patch modified, but a nifty (IMO) new one: ping forwarding for slirp using the unprivileged ICMP sockets of Linux 3.0. See commit log for a simple how-to.
My positive review of the previous version of 07-10 (posted on June 8) should still apply. Please apply.
Anthony Liguori
AppliedQuoted 8 lines · Jan Kiszka
Almost just a reposting of the previously sent series. No patch modified, but a nifty (IMO) new one: ping forwarding for slirp using the unprivileged ICMP sockets of Linux 3.0. See commit log for a simple how-to.
CC Gleb Natapov<[email protected]>CC Markus Armbruster<[email protected]>CC Peter Maydell<[email protected]>
Applied. Thanks.
The ICMP sockets thing is pretty cool!
Regards,
Anthony Liguori
Quoted 38 lines
Jan Kiszka (10):
slirp: Fix restricted mode
slirp: Canonicalize restrict syntax
slirp: Strictly associate DHCP/BOOTP and TFTP with virtual host
slirp: Replacem_freemwithm_free
slirp: Put forked exec into separate process group
slirp: Forward ICMP echo requests via unprivileged sockets
net: Improve layout of 'info network'
net: Refactornet_client_types
net: Dump client type 'info network'
net: Consistently useqemu_macaddr_default_if_unsethw/dp8393x.c | 2 +- hw/etraxfs_eth.c | 2 +- hw/mcf_fec.c | 2 +- hw/mipsnet.c | 2 +- hw/qdev.c | 2 +- hw/stellaris.c | 2 +- hw/xen_devconfig.c | 4 +- net.c | 65 +++++++++++++++++++++-------------- net.h | 8 +++-- net/slirp.c | 23 +++++++++---- qemu-options.hx | 4 +- slirp/ip_icmp.c | 95 +++++++++++++++++++++++++++++++++++++++++++++++++-- slirp/ip_icmp.h | 3 ++ slirp/ip_input.c | 30 +++-------------- slirp/ip_output.c | 4 +- slirp/mbuf.h | 3 -- slirp/misc.c | 16 ++++++++- slirp/slirp.c | 37 ++++++++++++++++++++ slirp/slirp.h | 5 +++ slirp/socket.c | 2 + slirp/tcp_input.c | 10 +++--- slirp/tcp_subr.c | 2 +- slirp/udp.c | 23 +++++++----- 23 files changed, 249 insertions(+), 97 deletions(-)