qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCHv9 0/10] slirp: Adding IPv6 support to Qemu -net user mode
@ 2016-02-22 19:28 Samuel Thibault
  2016-02-22 19:28 ` [Qemu-devel] [PATCHv9 01/10] slirp: Adding IPv6, ICMPv6 Echo and NDP autoconfiguration Samuel Thibault
                   ` (11 more replies)
  0 siblings, 12 replies; 51+ messages in thread
From: Samuel Thibault @ 2016-02-22 19:28 UTC (permalink / raw)
  To: qemu-devel
  Cc: Thomas Huth, zhanghailiang, Li Zhijian, Stefan Hajnoczi,
	Jason Wang, Dave Gilbert, Vasiliy Tolstov, Huangpeng, Gonglei,
	Jan Kiszka, Samuel Thibault, Guillaume Subiron

Hello,

This is another respin of IPv6 in Qemu -net user mode.


These patches add ICMPv6, NDP, make UDP and TCP compatible with IPv6, and add
TFTP over IPv6.


Difference with version 8 is:
- Fix freeing random number generator
- Fix coding style
- Fix prefix lengths in in6_equal_dns macro

Here is a summary of the patches:
Guillaume Subiron (7):
  slirp: Adding IPv6, ICMPv6 Echo and NDP autoconfiguration
  slirp: Adding IPv6 UDP support
  slirp: Factorizing tcpiphdr structure with an union
  slirp: Generalizing and neutralizing various TCP functions before
    adding IPv6 stuff
  slirp: Reindent after refactoring
  slirp: Handle IPv6 in TCP functions
  slirp: Adding IPv6 address for DNS relay

Thomas Huth (1):
  slirp: Add IPv6 support to the TFTP code

Yann Bordenave (2):
  slirp: Adding ICMPv6 error sending
  qapi-schema, qemu-options & slirp: Adding Qemu options for IPv6
    addresses

 net/net.c           |  31 ++++
 net/slirp.c         |  69 ++++++++-
 qapi-schema.json    |  40 +++--
 qemu-options.hx     |  18 ++-
 slirp/Makefile.objs |   6 +-
 slirp/cksum.c       |  25 ++++
 slirp/if.c          |   2 +-
 slirp/if.h          |   4 +-
 slirp/ip6.h         | 142 ++++++++++++++++++
 slirp/ip6_icmp.c    | 411 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 slirp/ip6_icmp.h    | 213 +++++++++++++++++++++++++++
 slirp/ip6_input.c   |  73 ++++++++++
 slirp/ip6_output.c  |  38 +++++
 slirp/ip_icmp.c     |  12 +-
 slirp/ip_icmp.h     |   4 +-
 slirp/ip_input.c    |  10 +-
 slirp/libslirp.h    |   8 +-
 slirp/mbuf.c        |   4 +-
 slirp/ndp_table.c   |  84 +++++++++++
 slirp/slirp.c       |  81 +++++++++--
 slirp/slirp.h       |  43 +++++-
 slirp/socket.c      |  54 ++++++-
 slirp/socket.h      |  13 ++
 slirp/tcp.h         |   2 +
 slirp/tcp_input.c   | 181 ++++++++++++++++-------
 slirp/tcp_output.c  |  51 +++++--
 slirp/tcp_subr.c    | 114 +++++++++++----
 slirp/tcp_timer.c   |   3 +-
 slirp/tcpip.h       |  40 ++++-
 slirp/tftp.c        | 133 +++++++++--------
 slirp/tftp.h        |   7 +-
 slirp/udp.c         |  19 ++-
 slirp/udp.h         |   5 +
 slirp/udp6.c        | 167 +++++++++++++++++++++
 34 files changed, 1877 insertions(+), 230 deletions(-)
 create mode 100644 slirp/ip6.h
 create mode 100644 slirp/ip6_icmp.c
 create mode 100644 slirp/ip6_icmp.h
 create mode 100644 slirp/ip6_input.c
 create mode 100644 slirp/ip6_output.c
 create mode 100644 slirp/ndp_table.c
 create mode 100644 slirp/udp6.c

-- 
2.7.0

^ permalink raw reply	[flat|nested] 51+ messages in thread

* [Qemu-devel] [PATCHv9 01/10] slirp: Adding IPv6, ICMPv6 Echo and NDP autoconfiguration
  2016-02-22 19:28 [Qemu-devel] [PATCHv9 0/10] slirp: Adding IPv6 support to Qemu -net user mode Samuel Thibault
@ 2016-02-22 19:28 ` Samuel Thibault
  2016-03-07  6:53   ` Jason Wang
  2016-02-22 19:28 ` [Qemu-devel] [PATCHv9 02/10] slirp: Adding ICMPv6 error sending Samuel Thibault
                   ` (10 subsequent siblings)
  11 siblings, 1 reply; 51+ messages in thread
From: Samuel Thibault @ 2016-02-22 19:28 UTC (permalink / raw)
  To: qemu-devel
  Cc: Thomas Huth, zhanghailiang, Li Zhijian, Stefan Hajnoczi,
	Jason Wang, Dave Gilbert, Vasiliy Tolstov, Huangpeng, Gonglei,
	Jan Kiszka, Samuel Thibault, Guillaume Subiron

From: Guillaume Subiron <maethor@subiron.org>

This patch adds the functions needed to handle IPv6 packets. ICMPv6 and
NDP headers are implemented.

Slirp is now able to send NDP Router or Neighbor Advertisement when it
receives Router or Neighbor Solicitation. Using a 64bit-sized IPv6
prefix, the guest is now able to perform stateless autoconfiguration
(SLAAC) and to compute its IPv6 address.

This patch adds an ndp_table, mainly inspired by arp_table, to keep an
NDP cache and manage network address resolution.
Slirp regularly sends NDP Neighbor Advertisement, as recommended by the
RFC, to make the guest refresh its route.

This also adds ip6_cksum() to compute ICMPv6 checksums using IPv6
pseudo-header.

Some #define ETH_* are moved upper in slirp.h to make them accessible to
other slirp/*.h

Signed-off-by: Guillaume Subiron <maethor@subiron.org>
Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
Reviewed-by: Thomas Huth <thuth@redhat.com>
---
 slirp/Makefile.objs |   6 +-
 slirp/cksum.c       |  25 ++++
 slirp/if.c          |   2 +-
 slirp/ip6.h         | 138 +++++++++++++++++++++
 slirp/ip6_icmp.c    | 347 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 slirp/ip6_icmp.h    | 203 ++++++++++++++++++++++++++++++
 slirp/ip6_input.c   |  69 +++++++++++
 slirp/ip6_output.c  |  38 ++++++
 slirp/ndp_table.c   |  84 +++++++++++++
 slirp/slirp.c       |  51 +++++++-
 slirp/slirp.h       |  37 ++++++
 slirp/socket.h      |   7 ++
 12 files changed, 1001 insertions(+), 6 deletions(-)
 create mode 100644 slirp/ip6.h
 create mode 100644 slirp/ip6_icmp.c
 create mode 100644 slirp/ip6_icmp.h
 create mode 100644 slirp/ip6_input.c
 create mode 100644 slirp/ip6_output.c
 create mode 100644 slirp/ndp_table.c

diff --git a/slirp/Makefile.objs b/slirp/Makefile.objs
index 2daa9dc..4e3a289 100644
--- a/slirp/Makefile.objs
+++ b/slirp/Makefile.objs
@@ -1,3 +1,5 @@
-common-obj-y = cksum.o if.o ip_icmp.o ip_input.o ip_output.o dnssearch.o
+common-obj-y = cksum.o if.o ip_icmp.o ip6_icmp.o ip6_input.o ip6_output.o \
+               ip_input.o ip_output.o dnssearch.o
 common-obj-y += slirp.o mbuf.o misc.o sbuf.o socket.o tcp_input.o tcp_output.o
-common-obj-y += tcp_subr.o tcp_timer.o udp.o bootp.o tftp.o arp_table.o
+common-obj-y += tcp_subr.o tcp_timer.o udp.o bootp.o tftp.o arp_table.o \
+                ndp_table.o
diff --git a/slirp/cksum.c b/slirp/cksum.c
index bc0d017..2ad0e65 100644
--- a/slirp/cksum.c
+++ b/slirp/cksum.c
@@ -138,3 +138,28 @@ cont:
 	REDUCE;
 	return (~sum & 0xffff);
 }
+
+int ip6_cksum(struct mbuf *m)
+{
+    /* TODO: Optimize this by being able to pass the ip6_pseudohdr to cksum
+     * separately from the mbuf */
+    struct ip6 save_ip, *ip = mtod(m, struct ip6 *);
+    struct ip6_pseudohdr *ih = mtod(m, struct ip6_pseudohdr *);
+    int sum;
+
+    save_ip = *ip;
+
+    ih->ih_src = save_ip.ip_src;
+    ih->ih_dst = save_ip.ip_dst;
+    ih->ih_pl = htonl((uint32_t)ntohs(save_ip.ip_pl));
+    ih->ih_zero_hi = 0;
+    ih->ih_zero_lo = 0;
+    ih->ih_nh = save_ip.ip_nh;
+
+    sum = cksum(m, ((int)sizeof(struct ip6_pseudohdr))
+                    + ntohl(ih->ih_pl));
+
+    *ip = save_ip;
+
+    return sum;
+}
diff --git a/slirp/if.c b/slirp/if.c
index 93d7cc0..2e21f43 100644
--- a/slirp/if.c
+++ b/slirp/if.c
@@ -194,7 +194,7 @@ void if_start(Slirp *slirp)
 
         /* Try to send packet unless it already expired */
         if (ifm->expiration_date >= now && !if_encap(slirp, ifm)) {
-            /* Packet is delayed due to pending ARP resolution */
+            /* Packet is delayed due to pending ARP or NDP resolution */
             continue;
         }
 
diff --git a/slirp/ip6.h b/slirp/ip6.h
new file mode 100644
index 0000000..55e52a1
--- /dev/null
+++ b/slirp/ip6.h
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2013
+ * Guillaume Subiron, Yann Bordenave, Serigne Modou Wagne.
+ */
+
+#ifndef SLIRP_IP6_H_
+#define SLIRP_IP6_H_
+
+#include <netinet/in.h>
+#include "net/eth.h"
+
+#define ALLNODES_MULTICAST  { .s6_addr = \
+                            { 0xff, 0x02, 0x00, 0x00,\
+                            0x00, 0x00, 0x00, 0x00,\
+                            0x00, 0x00, 0x00, 0x00,\
+                            0x00, 0x00, 0x00, 0x01 } }
+
+#define SOLICITED_NODE_PREFIX { .s6_addr = \
+                            { 0xff, 0x02, 0x00, 0x00,\
+                            0x00, 0x00, 0x00, 0x00,\
+                            0x00, 0x00, 0x00, 0x01,\
+                            0xff, 0x00, 0x00, 0x00 } }
+
+#define LINKLOCAL_ADDR  { .s6_addr = \
+                        { 0xfe, 0x80, 0x00, 0x00,\
+                        0x00, 0x00, 0x00, 0x00,\
+                        0x00, 0x00, 0x00, 0x00,\
+                        0x00, 0x00, 0x00, 0x02 } }
+
+static inline bool in6_equal(const struct in6_addr *a, const struct in6_addr *b)
+{
+    return memcmp(a, b, sizeof(*a)) == 0;
+}
+
+static inline bool in6_equal_net(const struct in6_addr *a,
+                                 const struct in6_addr *b,
+                                 int prefix_len)
+{
+    if (memcmp(a, b, prefix_len / 8) != 0) {
+        return 0;
+    }
+
+    if (prefix_len % 8 == 0) {
+        return 1;
+    }
+
+    return a->s6_addr[prefix_len / 8] >> (8 - (prefix_len % 8))
+        == b->s6_addr[prefix_len / 8] >> (8 - (prefix_len % 8));
+}
+
+static inline bool in6_equal_mach(const struct in6_addr *a,
+                                  const struct in6_addr *b,
+                                  int prefix_len)
+{
+    if (memcmp(&(a->s6_addr[(prefix_len + 7) / 8]),
+               &(b->s6_addr[(prefix_len + 7) / 8]),
+               16 - (prefix_len + 7) / 8) != 0) {
+        return 0;
+    }
+
+    if (prefix_len % 8 == 0) {
+        return 1;
+    }
+
+    return (a->s6_addr[prefix_len / 8] & ((1U << (8 - (prefix_len % 8))) - 1))
+        == (b->s6_addr[prefix_len / 8] & ((1U << (8 - (prefix_len % 8))) - 1));
+}
+
+
+#define in6_equal_router(a)\
+    ((in6_equal_net(a, &slirp->vprefix_addr6, slirp->vprefix_len)\
+      && in6_equal_mach(a, &slirp->vhost_addr6, slirp->vprefix_len))\
+  || (in6_equal_net(a, &(struct in6_addr)LINKLOCAL_ADDR, 64)\
+      && in6_equal_mach(a, &slirp->vhost_addr6, 64)))
+
+#define in6_equal_dns(a) 0
+
+#define in6_equal_host(a)\
+    (in6_equal_router(a) || in6_equal_dns(a))
+
+#define in6_solicitednode_multicast(a)\
+    (in6_equal_net(a, &(struct in6_addr)SOLICITED_NODE_PREFIX, 104))
+
+/* Compute emulated host MAC address from its ipv6 address */
+static inline void in6_compute_ethaddr(struct in6_addr ip,
+                                       uint8_t eth[ETH_ALEN])
+{
+    eth[0] = 0x52;
+    eth[1] = 0x56;
+    memcpy(&eth[2], &ip.s6_addr[16 - (ETH_ALEN - 2)], ETH_ALEN - 2);
+}
+
+/*
+ * Definitions for internet protocol version 6.
+ * Per RFC 2460, December 1998.
+ */
+#define IP6VERSION      6
+#define IP6_HOP_LIMIT 255
+
+/*
+ * Structure of an internet header, naked of options.
+ */
+struct ip6 {
+#ifdef HOST_WORDS_BIGENDIAN
+    uint32_t
+        ip_v:4,         /* version */
+        ip_tc_hi:4,     /* traffic class */
+        ip_tc_lo:4,
+        ip_fl_hi:4,     /* flow label */
+        ip_fl_lo:16;
+#else
+    uint32_t
+        ip_tc_hi:4,
+        ip_v:4,
+        ip_fl_hi:4,
+        ip_tc_lo:4,
+        ip_fl_lo:16;
+#endif
+    uint16_t    ip_pl;               /* payload length */
+    uint8_t     ip_nh;               /* next header */
+    uint8_t     ip_hl;               /* hop limit */
+    struct in6_addr ip_src, ip_dst;  /* source and dest address */
+} QEMU_PACKED;
+
+/*
+ * IPv6 pseudo-header used by upper-layer protocols
+ */
+struct ip6_pseudohdr {
+    struct      in6_addr ih_src;  /* source internet address */
+    struct      in6_addr ih_dst;  /* destination internet address */
+    uint32_t    ih_pl;            /* upper-layer packet length */
+    uint16_t    ih_zero_hi;       /* zero */
+    uint8_t     ih_zero_lo;       /* zero */
+    uint8_t     ih_nh;            /* next header */
+} QEMU_PACKED;
+
+
+#endif
diff --git a/slirp/ip6_icmp.c b/slirp/ip6_icmp.c
new file mode 100644
index 0000000..029d297
--- /dev/null
+++ b/slirp/ip6_icmp.c
@@ -0,0 +1,347 @@
+/*
+ * Copyright (c) 2013
+ * Guillaume Subiron, Yann Bordenave, Serigne Modou Wagne.
+ */
+
+#include "qemu/osdep.h"
+#include "slirp.h"
+#include "ip6_icmp.h"
+#include "qemu/timer.h"
+#include "qemu/error-report.h"
+#include "qemu/log.h"
+#include <time.h>
+
+#define NDP_Interval g_rand_int_range(slirp->grand, NDP_MinRtrAdvInterval, NDP_MaxRtrAdvInterval)
+
+static void ra_timer_handler(void *opaque)
+{
+    Slirp *slirp = opaque;
+    timer_mod(slirp->ra_timer,
+              qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + NDP_Interval);
+    ndp_send_ra(slirp);
+}
+
+void icmp6_init(Slirp *slirp)
+{
+    slirp->ra_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL, ra_timer_handler, slirp);
+    timer_mod(slirp->ra_timer,
+              qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + NDP_Interval);
+}
+
+void icmp6_cleanup(Slirp *slirp)
+{
+    timer_del(slirp->ra_timer);
+    timer_free(slirp->ra_timer);
+}
+
+static void icmp6_send_echoreply(struct mbuf *m, Slirp *slirp, struct ip6 *ip,
+        struct icmp6 *icmp)
+{
+    struct mbuf *t = m_get(slirp);
+    t->m_len = sizeof(struct ip6) + ntohs(ip->ip_pl);
+    memcpy(t->m_data, m->m_data, t->m_len);
+
+    /* IPv6 Packet */
+    struct ip6 *rip = mtod(t, struct ip6 *);
+    rip->ip_dst = ip->ip_src;
+    rip->ip_src = ip->ip_dst;
+
+    /* ICMPv6 packet */
+    t->m_data += sizeof(struct ip6);
+    struct icmp6 *ricmp = mtod(t, struct icmp6 *);
+    ricmp->icmp6_type = ICMP6_ECHO_REPLY;
+    ricmp->icmp6_cksum = 0;
+
+    /* Checksum */
+    t->m_data -= sizeof(struct ip6);
+    ricmp->icmp6_cksum = ip6_cksum(t);
+
+    ip6_output(NULL, t, 0);
+}
+
+/*
+ * Send NDP Router Advertisement
+ */
+void ndp_send_ra(Slirp *slirp)
+{
+    DEBUG_CALL("ndp_send_ra");
+
+    /* Build IPv6 packet */
+    struct mbuf *t = m_get(slirp);
+    struct ip6 *rip = mtod(t, struct ip6 *);
+    rip->ip_src = (struct in6_addr)LINKLOCAL_ADDR;
+    rip->ip_dst = (struct in6_addr)ALLNODES_MULTICAST;
+    rip->ip_nh = IPPROTO_ICMPV6;
+    rip->ip_pl = htons(ICMP6_NDP_RA_MINLEN
+                        + NDPOPT_LINKLAYER_LEN
+                        + NDPOPT_PREFIXINFO_LEN);
+    t->m_len = sizeof(struct ip6) + ntohs(rip->ip_pl);
+
+    /* Build ICMPv6 packet */
+    t->m_data += sizeof(struct ip6);
+    struct icmp6 *ricmp = mtod(t, struct icmp6 *);
+    ricmp->icmp6_type = ICMP6_NDP_RA;
+    ricmp->icmp6_code = 0;
+    ricmp->icmp6_cksum = 0;
+
+    /* NDP */
+    ricmp->icmp6_nra.chl = NDP_AdvCurHopLimit;
+    ricmp->icmp6_nra.M = NDP_AdvManagedFlag;
+    ricmp->icmp6_nra.O = NDP_AdvOtherConfigFlag;
+    ricmp->icmp6_nra.reserved = 0;
+    ricmp->icmp6_nra.lifetime = htons(NDP_AdvDefaultLifetime);
+    ricmp->icmp6_nra.reach_time = htonl(NDP_AdvReachableTime);
+    ricmp->icmp6_nra.retrans_time = htonl(NDP_AdvRetransTime);
+
+    /* Source link-layer address (NDP option) */
+    t->m_data += ICMP6_NDP_RA_MINLEN;
+    struct ndpopt *opt = mtod(t, struct ndpopt *);
+    opt->ndpopt_type = NDPOPT_LINKLAYER_SOURCE;
+    opt->ndpopt_len = NDPOPT_LINKLAYER_LEN / 8;
+    in6_compute_ethaddr(rip->ip_src, opt->ndpopt_linklayer);
+
+    /* Prefix information (NDP option) */
+    t->m_data += NDPOPT_LINKLAYER_LEN;
+    struct ndpopt *opt2 = mtod(t, struct ndpopt *);
+    opt2->ndpopt_type = NDPOPT_PREFIX_INFO;
+    opt2->ndpopt_len = NDPOPT_PREFIXINFO_LEN / 8;
+    opt2->ndpopt_prefixinfo.prefix_length = slirp->vprefix_len;
+    opt2->ndpopt_prefixinfo.L = 1;
+    opt2->ndpopt_prefixinfo.A = 1;
+    opt2->ndpopt_prefixinfo.reserved1 = 0;
+    opt2->ndpopt_prefixinfo.valid_lt = htonl(NDP_AdvValidLifetime);
+    opt2->ndpopt_prefixinfo.pref_lt = htonl(NDP_AdvPrefLifetime);
+    opt2->ndpopt_prefixinfo.reserved2 = 0;
+    opt2->ndpopt_prefixinfo.prefix = slirp->vprefix_addr6;
+
+    /* ICMPv6 Checksum */
+    t->m_data -= NDPOPT_LINKLAYER_LEN;
+    t->m_data -= ICMP6_NDP_RA_MINLEN;
+    t->m_data -= sizeof(struct ip6);
+    ricmp->icmp6_cksum = ip6_cksum(t);
+
+    ip6_output(NULL, t, 0);
+}
+
+/*
+ * Send NDP Neighbor Solitication
+ */
+void ndp_send_ns(Slirp *slirp, struct in6_addr addr)
+{
+    char addrstr[INET6_ADDRSTRLEN];
+    inet_ntop(AF_INET6, &addr, addrstr, INET6_ADDRSTRLEN);
+    DEBUG_CALL("ndp_send_ns");
+    DEBUG_ARG("target = %s", addrstr);
+
+    /* Build IPv6 packet */
+    struct mbuf *t = m_get(slirp);
+    struct ip6 *rip = mtod(t, struct ip6 *);
+    rip->ip_src = slirp->vhost_addr6;
+    rip->ip_dst = (struct in6_addr)SOLICITED_NODE_PREFIX;
+    memcpy(&rip->ip_dst.s6_addr[13], &addr.s6_addr[13], 3);
+    rip->ip_nh = IPPROTO_ICMPV6;
+    rip->ip_pl = htons(ICMP6_NDP_NS_MINLEN + NDPOPT_LINKLAYER_LEN);
+    t->m_len = sizeof(struct ip6) + ntohs(rip->ip_pl);
+
+    /* Build ICMPv6 packet */
+    t->m_data += sizeof(struct ip6);
+    struct icmp6 *ricmp = mtod(t, struct icmp6 *);
+    ricmp->icmp6_type = ICMP6_NDP_NS;
+    ricmp->icmp6_code = 0;
+    ricmp->icmp6_cksum = 0;
+
+    /* NDP */
+    ricmp->icmp6_nns.reserved = 0;
+    ricmp->icmp6_nns.target = addr;
+
+    /* Build NDP option */
+    t->m_data += ICMP6_NDP_NS_MINLEN;
+    struct ndpopt *opt = mtod(t, struct ndpopt *);
+    opt->ndpopt_type = NDPOPT_LINKLAYER_SOURCE;
+    opt->ndpopt_len = NDPOPT_LINKLAYER_LEN / 8;
+    in6_compute_ethaddr(slirp->vhost_addr6, opt->ndpopt_linklayer);
+
+    /* ICMPv6 Checksum */
+    t->m_data -= ICMP6_NDP_NA_MINLEN;
+    t->m_data -= sizeof(struct ip6);
+    ricmp->icmp6_cksum = ip6_cksum(t);
+
+    ip6_output(NULL, t, 1);
+}
+
+/*
+ * Send NDP Neighbor Advertisement
+ */
+static void ndp_send_na(Slirp *slirp, struct ip6 *ip, struct icmp6 *icmp)
+{
+    /* Build IPv6 packet */
+    struct mbuf *t = m_get(slirp);
+    struct ip6 *rip = mtod(t, struct ip6 *);
+    rip->ip_src = icmp->icmp6_nns.target;
+    if (IN6_IS_ADDR_UNSPECIFIED(&ip->ip_src)) {
+        rip->ip_dst = (struct in6_addr)ALLNODES_MULTICAST;
+    } else {
+        rip->ip_dst = ip->ip_src;
+    }
+    rip->ip_nh = IPPROTO_ICMPV6;
+    rip->ip_pl = htons(ICMP6_NDP_NA_MINLEN
+                        + NDPOPT_LINKLAYER_LEN);
+    t->m_len = sizeof(struct ip6) + ntohs(rip->ip_pl);
+
+    /* Build ICMPv6 packet */
+    t->m_data += sizeof(struct ip6);
+    struct icmp6 *ricmp = mtod(t, struct icmp6 *);
+    ricmp->icmp6_type = ICMP6_NDP_NA;
+    ricmp->icmp6_code = 0;
+    ricmp->icmp6_cksum = 0;
+
+    /* NDP */
+    ricmp->icmp6_nna.R = NDP_IsRouter;
+    ricmp->icmp6_nna.S = !IN6_IS_ADDR_MULTICAST(&rip->ip_dst);
+    ricmp->icmp6_nna.O = 1;
+    ricmp->icmp6_nna.reserved_hi = 0;
+    ricmp->icmp6_nna.reserved_lo = 0;
+    ricmp->icmp6_nna.target = icmp->icmp6_nns.target;
+
+    /* Build NDP option */
+    t->m_data += ICMP6_NDP_NA_MINLEN;
+    struct ndpopt *opt = mtod(t, struct ndpopt *);
+    opt->ndpopt_type = NDPOPT_LINKLAYER_TARGET;
+    opt->ndpopt_len = NDPOPT_LINKLAYER_LEN / 8;
+    in6_compute_ethaddr(ricmp->icmp6_nna.target,
+                    opt->ndpopt_linklayer);
+
+    /* ICMPv6 Checksum */
+    t->m_data -= ICMP6_NDP_NA_MINLEN;
+    t->m_data -= sizeof(struct ip6);
+    ricmp->icmp6_cksum = ip6_cksum(t);
+
+    ip6_output(NULL, t, 0);
+}
+
+/*
+ * Process a NDP message
+ */
+static void ndp_input(struct mbuf *m, Slirp *slirp, struct ip6 *ip,
+        struct icmp6 *icmp)
+{
+    m->m_len += ETH_HLEN;
+    m->m_data -= ETH_HLEN;
+    struct ethhdr *eth = mtod(m, struct ethhdr *);
+    m->m_len -= ETH_HLEN;
+    m->m_data += ETH_HLEN;
+
+    switch (icmp->icmp6_type) {
+    case ICMP6_NDP_RS:
+        DEBUG_CALL(" type = Router Solicitation");
+        if (ip->ip_hl == 255
+                && icmp->icmp6_code == 0
+                && ntohs(ip->ip_pl) >= ICMP6_NDP_RS_MINLEN) {
+            /* Gratuitous NDP */
+            ndp_table_add(slirp, ip->ip_src, eth->h_source);
+
+            ndp_send_ra(slirp);
+        }
+        break;
+
+    case ICMP6_NDP_RA:
+        DEBUG_CALL(" type = Router Advertisement");
+        qemu_log_mask(LOG_GUEST_ERROR,
+                "Warning: guest sent NDP RA, but shouldn't");
+        break;
+
+    case ICMP6_NDP_NS:
+        DEBUG_CALL(" type = Neighbor Solicitation");
+        if (ip->ip_hl == 255
+                && icmp->icmp6_code == 0
+                && !IN6_IS_ADDR_MULTICAST(&icmp->icmp6_nns.target)
+                && ntohs(ip->ip_pl) >= ICMP6_NDP_NS_MINLEN
+                && (!IN6_IS_ADDR_UNSPECIFIED(&ip->ip_src)
+                    || in6_solicitednode_multicast(&ip->ip_dst))) {
+            if (in6_equal_host(&icmp->icmp6_nns.target)) {
+                /* Gratuitous NDP */
+                ndp_table_add(slirp, ip->ip_src, eth->h_source);
+                ndp_send_na(slirp, ip, icmp);
+            }
+        }
+        break;
+
+    case ICMP6_NDP_NA:
+        DEBUG_CALL(" type = Neighbor Advertisement");
+        if (ip->ip_hl == 255
+                && icmp->icmp6_code == 0
+                && ntohs(ip->ip_pl) >= ICMP6_NDP_NA_MINLEN
+                && !IN6_IS_ADDR_MULTICAST(&icmp->icmp6_nna.target)
+                && (!IN6_IS_ADDR_MULTICAST(&ip->ip_dst)
+                    || icmp->icmp6_nna.S == 0)) {
+            ndp_table_add(slirp, ip->ip_src, eth->h_source);
+        }
+        break;
+
+    case ICMP6_NDP_REDIRECT:
+        DEBUG_CALL(" type = Redirect");
+        qemu_log_mask(LOG_GUEST_ERROR,
+                "Warning: guest sent NDP REDIRECT, but shouldn't");
+        break;
+    }
+}
+
+/*
+ * Process a received ICMPv6 message.
+ */
+void icmp6_input(struct mbuf *m)
+{
+    struct icmp6 *icmp;
+    struct ip6 *ip = mtod(m, struct ip6 *);
+    Slirp *slirp = m->slirp;
+    int hlen = sizeof(struct ip6);
+
+    DEBUG_CALL("icmp6_input");
+    DEBUG_ARG("m = %lx", (long) m);
+    DEBUG_ARG("m_len = %d", m->m_len);
+
+    if (ntohs(ip->ip_pl) < ICMP6_MINLEN) {
+        goto end;
+    }
+
+    if (ip6_cksum(m)) {
+        goto end;
+    }
+
+    m->m_len -= hlen;
+    m->m_data += hlen;
+    icmp = mtod(m, struct icmp6 *);
+    m->m_len += hlen;
+    m->m_data -= hlen;
+
+    DEBUG_ARG("icmp6_type = %d", icmp->icmp6_type);
+    switch (icmp->icmp6_type) {
+    case ICMP6_ECHO_REQUEST:
+        if (in6_equal_host(&ip->ip_dst)) {
+            icmp6_send_echoreply(m, slirp, ip, icmp);
+        } else {
+            /* TODO */
+            error_report("external icmpv6 not supported yet");
+        }
+        break;
+
+    case ICMP6_NDP_RS:
+    case ICMP6_NDP_RA:
+    case ICMP6_NDP_NS:
+    case ICMP6_NDP_NA:
+    case ICMP6_NDP_REDIRECT:
+        ndp_input(m, slirp, ip, icmp);
+        break;
+
+    case ICMP6_UNREACH:
+    case ICMP6_TOOBIG:
+    case ICMP6_TIMXCEED:
+    case ICMP6_PARAMPROB:
+        /* XXX? report error? close socket? */
+    default:
+        break;
+    }
+
+end:
+    m_free(m);
+}
diff --git a/slirp/ip6_icmp.h b/slirp/ip6_icmp.h
new file mode 100644
index 0000000..b2c40d6
--- /dev/null
+++ b/slirp/ip6_icmp.h
@@ -0,0 +1,203 @@
+/*
+ * Copyright (c) 2013
+ * Guillaume Subiron, Yann Bordenave, Serigne Modou Wagne.
+ */
+
+#ifndef SLIRP_NETINET_ICMP6_H_
+#define SLIRP_NETINET_ICMP6_H_
+
+/*
+ * Interface Control Message Protocol version 6 Definitions.
+ * Per RFC 4443, March 2006.
+ *
+ * Network Discover Protocol Definitions.
+ * Per RFC 4861, September 2007.
+ */
+
+struct icmp6_echo { /* Echo Messages */
+    uint16_t id;
+    uint16_t seq_num;
+};
+
+/*
+ * NDP Messages
+ */
+struct ndp_rs {     /* Router Solicitation Message */
+    uint32_t reserved;
+};
+
+struct ndp_ra {     /* Router Advertisement Message */
+    uint8_t chl;    /* Cur Hop Limit */
+#ifdef HOST_WORDS_BIGENDIAN
+    uint8_t
+        M:1,
+        O:1,
+        reserved:6;
+#else
+    uint8_t
+        reserved:6,
+        O:1,
+        M:1;
+#endif
+    uint16_t lifetime;      /* Router Lifetime */
+    uint32_t reach_time;    /* Reachable Time */
+    uint32_t retrans_time;  /* Retrans Timer */
+} QEMU_PACKED;
+
+struct ndp_ns {     /* Neighbor Solicitation Message */
+    uint32_t reserved;
+    struct in6_addr target; /* Target Address */
+} QEMU_PACKED;
+
+struct ndp_na {     /* Neighbor Advertisement Message */
+#ifdef HOST_WORDS_BIGENDIAN
+    uint32_t
+        R:1,                /* Router Flag */
+        S:1,                /* Solicited Flag */
+        O:1,                /* Override Flag */
+        reserved_hi:5,
+        reserved_lo:24;
+#else
+    uint32_t
+        reserved_hi:5,
+        O:1,
+        S:1,
+        R:1,
+        reserved_lo:24;
+#endif
+    struct in6_addr target; /* Target Address */
+} QEMU_PACKED;
+
+struct ndp_redirect {
+    uint32_t reserved;
+    struct in6_addr target; /* Target Address */
+    struct in6_addr dest;   /* Destination Address */
+} QEMU_PACKED;
+
+/*
+ * Structure of an icmpv6 header.
+ */
+struct icmp6 {
+    uint8_t     icmp6_type;         /* type of message, see below */
+    uint8_t     icmp6_code;         /* type sub code */
+    uint16_t    icmp6_cksum;        /* ones complement cksum of struct */
+    union {
+        struct icmp6_echo echo;
+        struct ndp_rs ndp_rs;
+        struct ndp_ra ndp_ra;
+        struct ndp_ns ndp_ns;
+        struct ndp_na ndp_na;
+        struct ndp_redirect ndp_redirect;
+    } icmp6_body;
+#define icmp6_echo icmp6_body.echo
+#define icmp6_nrs icmp6_body.ndp_rs
+#define icmp6_nra icmp6_body.ndp_ra
+#define icmp6_nns icmp6_body.ndp_ns
+#define icmp6_nna icmp6_body.ndp_na
+#define icmp6_redirect icmp6_body.ndp_redirect
+} QEMU_PACKED;
+
+#define ICMP6_MINLEN    4
+#define ICMP6_ECHO_MINLEN   8
+#define ICMP6_NDP_RS_MINLEN 8
+#define ICMP6_NDP_RA_MINLEN 16
+#define ICMP6_NDP_NS_MINLEN 24
+#define ICMP6_NDP_NA_MINLEN 24
+#define ICMP6_NDP_REDIRECT_MINLEN 40
+
+/*
+ * NDP Options
+ */
+struct ndpopt {
+    uint8_t     ndpopt_type;                    /* Option type */
+    uint8_t     ndpopt_len;                     /* /!\ In units of 8 octets */
+    union {
+        unsigned char   linklayer_addr[6];      /* Source/Target Link-layer */
+        struct prefixinfo {                     /* Prefix Information */
+            uint8_t     prefix_length;
+#ifdef HOST_WORDS_BIGENDIAN
+            uint8_t     L:1, A:1, reserved1:6;
+#else
+            uint8_t     reserved1:6, A:1, L:1;
+#endif
+            uint32_t    valid_lt;               /* Valid Lifetime */
+            uint32_t    pref_lt;                /* Preferred Lifetime */
+            uint32_t    reserved2;
+            struct in6_addr prefix;
+        } QEMU_PACKED prefixinfo;
+    } ndpopt_body;
+#define ndpopt_linklayer ndpopt_body.linklayer_addr
+#define ndpopt_prefixinfo ndpopt_body.prefixinfo
+} QEMU_PACKED;
+
+/* NDP options type */
+#define NDPOPT_LINKLAYER_SOURCE     1   /* Source Link-Layer Address */
+#define NDPOPT_LINKLAYER_TARGET     2   /* Target Link-Layer Address */
+#define NDPOPT_PREFIX_INFO          3   /* Prefix Information */
+
+/* NDP options size, in octets. */
+#define NDPOPT_LINKLAYER_LEN    8
+#define NDPOPT_PREFIXINFO_LEN   32
+
+/*
+ * Definition of type and code field values.
+ * Per https://www.iana.org/assignments/icmpv6-parameters/icmpv6-parameters.xml
+ * Last Updated 2012-11-12
+ */
+
+/* Errors */
+#define ICMP6_UNREACH   1   /* Destination Unreachable */
+#define     ICMP6_UNREACH_NO_ROUTE      0   /* no route to dest */
+#define     ICMP6_UNREACH_DEST_PROHIB   1   /* com with dest prohibited */
+#define     ICMP6_UNREACH_SCOPE         2   /* beyond scope of src addr */
+#define     ICMP6_UNREACH_ADDRESS       3   /* address unreachable */
+#define     ICMP6_UNREACH_PORT          4   /* port unreachable */
+#define     ICMP6_UNREACH_SRC_FAIL      5   /* src addr failed */
+#define     ICMP6_UNREACH_REJECT_ROUTE  6   /* reject route to dest */
+#define     ICMP6_UNREACH_SRC_HDR_ERROR 7   /* error in src routing header */
+#define ICMP6_TOOBIG    2   /* Packet Too Big */
+#define ICMP6_TIMXCEED  3   /* Time Exceeded */
+#define     ICMP6_TIMXCEED_INTRANS      0   /* hop limit exceeded in transit */
+#define     ICMP6_TIMXCEED_REASS        1   /* ttl=0 in reass */
+#define ICMP6_PARAMPROB 4   /* Parameter Problem */
+#define     ICMP6_PARAMPROB_HDR_FIELD   0   /* err header field */
+#define     ICMP6_PARAMPROB_NXTHDR_TYPE 1   /* unrecognized Next Header type */
+#define     ICMP6_PARAMPROB_IPV6_OPT    2   /* unrecognized IPv6 option */
+
+/* Informational Messages */
+#define ICMP6_ECHO_REQUEST      128 /* Echo Request */
+#define ICMP6_ECHO_REPLY        129 /* Echo Reply */
+#define ICMP6_NDP_RS            133 /* Router Solicitation (NDP) */
+#define ICMP6_NDP_RA            134 /* Router Advertisement (NDP) */
+#define ICMP6_NDP_NS            135 /* Neighbor Solicitation (NDP) */
+#define ICMP6_NDP_NA            136 /* Neighbor Advertisement (NDP) */
+#define ICMP6_NDP_REDIRECT      137 /* Redirect Message (NDP) */
+
+/*
+ * Router Configuration Variables (rfc4861#section-6)
+ */
+#define NDP_IsRouter                1
+#define NDP_AdvSendAdvertisements   1
+#define NDP_MaxRtrAdvInterval       600000
+#define NDP_MinRtrAdvInterval       ((NDP_MaxRtrAdvInterval >= 9) ? \
+                                        NDP_MaxRtrAdvInterval / 3 : \
+                                        NDP_MaxRtrAdvInterval)
+#define NDP_AdvManagedFlag          0
+#define NDP_AdvOtherConfigFlag      0
+#define NDP_AdvLinkMTU              0
+#define NDP_AdvReachableTime        0
+#define NDP_AdvRetransTime          0
+#define NDP_AdvCurHopLimit          64
+#define NDP_AdvDefaultLifetime      ((3 * NDP_MaxRtrAdvInterval) / 1000)
+#define NDP_AdvValidLifetime        86400
+#define NDP_AdvOnLinkFlag           1
+#define NDP_AdvPrefLifetime         14400
+#define NDP_AdvAutonomousFlag       1
+
+void icmp6_init(Slirp *slirp);
+void icmp6_cleanup(Slirp *slirp);
+void icmp6_input(struct mbuf *);
+void ndp_send_ra(Slirp *slirp);
+void ndp_send_ns(Slirp *slirp, struct in6_addr addr);
+
+#endif
diff --git a/slirp/ip6_input.c b/slirp/ip6_input.c
new file mode 100644
index 0000000..df249f1
--- /dev/null
+++ b/slirp/ip6_input.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2013
+ * Guillaume Subiron, Yann Bordenave, Serigne Modou Wagne.
+ */
+
+#include "qemu/osdep.h"
+#include "slirp.h"
+#include "ip6_icmp.h"
+
+/*
+ * IP initialization: fill in IP protocol switch table.
+ * All protocols not implemented in kernel go to raw IP protocol handler.
+ */
+void ip6_init(Slirp *slirp)
+{
+    icmp6_init(slirp);
+}
+
+void ip6_cleanup(Slirp *slirp)
+{
+    icmp6_cleanup(slirp);
+}
+
+void ip6_input(struct mbuf *m)
+{
+    struct ip6 *ip6;
+
+    DEBUG_CALL("ip6_input");
+    DEBUG_ARG("m = %lx", (long)m);
+    DEBUG_ARG("m_len = %d", m->m_len);
+
+    if (m->m_len < sizeof(struct ip6)) {
+        goto bad;
+    }
+
+    ip6 = mtod(m, struct ip6 *);
+
+    if (ip6->ip_v != IP6VERSION) {
+        goto bad;
+    }
+
+    /* check ip_ttl for a correct ICMP reply */
+    if (ip6->ip_hl == 0) {
+        /*icmp_error(m, ICMP_TIMXCEED,ICMP_TIMXCEED_INTRANS, 0,"ttl");*/
+        goto bad;
+    }
+
+    /*
+     * Switch out to protocol's input routine.
+     */
+    switch (ip6->ip_nh) {
+#if 0
+    case IPPROTO_TCP:
+        tcp_input(m, hlen, (struct socket *)NULL);
+        break;
+    case IPPROTO_UDP:
+        udp_input(m, hlen);
+        break;
+#endif
+    case IPPROTO_ICMPV6:
+        icmp6_input(m);
+        break;
+    default:
+        m_free(m);
+    }
+    return;
+bad:
+    m_free(m);
+}
diff --git a/slirp/ip6_output.c b/slirp/ip6_output.c
new file mode 100644
index 0000000..2dd80f4
--- /dev/null
+++ b/slirp/ip6_output.c
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2013
+ * Guillaume Subiron, Yann Bordenave, Serigne Modou Wagne.
+ */
+
+#include "slirp.h"
+
+/* Number of packets queued before we start sending
+ * (to prevent allocing too many mbufs) */
+#define IF6_THRESH 10
+
+/*
+ * IPv6 output. The packet in mbuf chain m contains a IP header
+ */
+int ip6_output(struct socket *so, struct mbuf *m, int fast)
+{
+    struct ip6 *ip = mtod(m, struct ip6 *);
+
+    DEBUG_CALL("ip6_output");
+    DEBUG_ARG("so = %lx", (long)so);
+    DEBUG_ARG("m = %lx", (long)m);
+
+    /* Fill IPv6 header */
+    ip->ip_v = IP6VERSION;
+    ip->ip_hl = IP6_HOP_LIMIT;
+    ip->ip_tc_hi = 0;
+    ip->ip_tc_lo = 0;
+    ip->ip_fl_hi = 0;
+    ip->ip_fl_lo = 0;
+
+    if (fast) {
+        if_encap(m->slirp, m);
+    } else {
+        if_output(so, m);
+    }
+
+    return 0;
+}
diff --git a/slirp/ndp_table.c b/slirp/ndp_table.c
new file mode 100644
index 0000000..a715ddd
--- /dev/null
+++ b/slirp/ndp_table.c
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2013
+ * Guillaume Subiron, Yann Bordenave, Serigne Modou Wagne.
+ */
+
+#include "slirp.h"
+
+void ndp_table_add(Slirp *slirp, struct in6_addr ip_addr,
+                    uint8_t ethaddr[ETH_ALEN])
+{
+    NdpTable *ndp_table = &slirp->ndp_table;
+    int i;
+    char addrstr[INET6_ADDRSTRLEN];
+
+    DEBUG_CALL("ndp_table_add");
+    inet_ntop(AF_INET6, &(ip_addr), addrstr, INET6_ADDRSTRLEN);
+    DEBUG_ARG("ip = %s", addrstr);
+    DEBUG_ARGS((dfd, " hw addr = %02x:%02x:%02x:%02x:%02x:%02x\n",
+                ethaddr[0], ethaddr[1], ethaddr[2],
+                ethaddr[3], ethaddr[4], ethaddr[5]));
+
+    if (IN6_IS_ADDR_MULTICAST(&ip_addr) || IN6_IS_ADDR_UNSPECIFIED(&ip_addr)) {
+        /* Do not register multicast or unspecified addresses */
+        DEBUG_CALL(" abort: do not register multicast or unspecified address");
+        return;
+    }
+
+    /* Search for an entry */
+    for (i = 0; i < NDP_TABLE_SIZE; i++) {
+        if (in6_equal(&ndp_table->table[i].ip_addr, &ip_addr)) {
+            DEBUG_CALL(" already in table: update the entry");
+            /* Update the entry */
+            memcpy(ndp_table->table[i].eth_addr, ethaddr, ETH_ALEN);
+            return;
+        }
+    }
+
+    /* No entry found, create a new one */
+    DEBUG_CALL(" create new entry");
+    ndp_table->table[ndp_table->next_victim].ip_addr = ip_addr;
+    memcpy(ndp_table->table[ndp_table->next_victim].eth_addr,
+            ethaddr, ETH_ALEN);
+    ndp_table->next_victim = (ndp_table->next_victim + 1) % NDP_TABLE_SIZE;
+}
+
+bool ndp_table_search(Slirp *slirp, struct in6_addr ip_addr,
+                      uint8_t out_ethaddr[ETH_ALEN])
+{
+    NdpTable *ndp_table = &slirp->ndp_table;
+    int i;
+    char addrstr[INET6_ADDRSTRLEN];
+
+    DEBUG_CALL("ndp_table_search");
+    inet_ntop(AF_INET6, &(ip_addr), addrstr, INET6_ADDRSTRLEN);
+    DEBUG_ARG("ip = %s", addrstr);
+
+    assert(!IN6_IS_ADDR_UNSPECIFIED(&ip_addr));
+
+    /* Multicast address: fec0::abcd:efgh/8 -> 33:33:ab:cd:ef:gh */
+    if (IN6_IS_ADDR_MULTICAST(&ip_addr)) {
+        out_ethaddr[0] = 0x33; out_ethaddr[1] = 0x33;
+        out_ethaddr[2] = ip_addr.s6_addr[12];
+        out_ethaddr[3] = ip_addr.s6_addr[13];
+        out_ethaddr[4] = ip_addr.s6_addr[14];
+        out_ethaddr[5] = ip_addr.s6_addr[15];
+        DEBUG_ARGS((dfd, " multicast addr = %02x:%02x:%02x:%02x:%02x:%02x\n",
+                    out_ethaddr[0], out_ethaddr[1], out_ethaddr[2],
+                    out_ethaddr[3], out_ethaddr[4], out_ethaddr[5]));
+        return 1;
+    }
+
+    for (i = 0; i < NDP_TABLE_SIZE; i++) {
+        if (in6_equal(&ndp_table->table[i].ip_addr, &ip_addr)) {
+            memcpy(out_ethaddr, ndp_table->table[i].eth_addr,  ETH_ALEN);
+            DEBUG_ARGS((dfd, " found hw addr = %02x:%02x:%02x:%02x:%02x:%02x\n",
+                        out_ethaddr[0], out_ethaddr[1], out_ethaddr[2],
+                        out_ethaddr[3], out_ethaddr[4], out_ethaddr[5]));
+            return 1;
+        }
+    }
+
+    DEBUG_CALL(" ip not found in table");
+    return 0;
+}
diff --git a/slirp/slirp.c b/slirp/slirp.c
index 0466d33..c986e0b 100644
--- a/slirp/slirp.c
+++ b/slirp/slirp.c
@@ -210,10 +210,12 @@ Slirp *slirp_init(int restricted, struct in_addr vnetwork,
 
     slirp_init_once();
 
+    slirp->grand = g_rand_new();
     slirp->restricted = restricted;
 
     if_init(slirp);
     ip_init(slirp);
+    ip6_init(slirp);
 
     /* Initialise mbufs *after* setting the MTU */
     m_init(slirp);
@@ -221,6 +223,9 @@ Slirp *slirp_init(int restricted, struct in_addr vnetwork,
     slirp->vnetwork_addr = vnetwork;
     slirp->vnetwork_mask = vnetmask;
     slirp->vhost_addr = vhost;
+    inet_pton(AF_INET6, "fec0::0", &slirp->vprefix_addr6);
+    slirp->vprefix_len = 64;
+    inet_pton(AF_INET6, "fec0::2", &slirp->vhost_addr6);
     if (vhostname) {
         pstrcpy(slirp->client_hostname, sizeof(slirp->client_hostname),
                 vhostname);
@@ -251,8 +256,11 @@ void slirp_cleanup(Slirp *slirp)
     unregister_savevm(NULL, "slirp", slirp);
 
     ip_cleanup(slirp);
+    ip6_cleanup(slirp);
     m_cleanup(slirp);
 
+    g_rand_free(slirp->grand);
+
     g_free(slirp->vdnssearch);
     g_free(slirp->tftp_prefix);
     g_free(slirp->bootp_filename);
@@ -744,6 +752,7 @@ void slirp_input(Slirp *slirp, const uint8_t *pkt, int pkt_len)
         arp_input(slirp, pkt, pkt_len);
         break;
     case ETH_P_IP:
+    case ETH_P_IPV6:
         m = m_get(slirp);
         if (!m)
             return;
@@ -757,8 +766,13 @@ void slirp_input(Slirp *slirp, const uint8_t *pkt, int pkt_len)
         m->m_data += 2 + ETH_HLEN;
         m->m_len -= 2 + ETH_HLEN;
 
-        ip_input(m);
+        if (proto == ETH_P_IP) {
+            ip_input(m);
+        } else if (proto == ETH_P_IPV6) {
+            ip6_input(m);
+        }
         break;
+
     default:
         break;
     }
@@ -826,6 +840,31 @@ static int if_encap4(Slirp *slirp, struct mbuf *ifm, struct ethhdr *eh,
     }
 }
 
+/* Prepare the IPv6 packet to be sent to the ethernet device. Returns 1 if no
+ * packet should be sent, 0 if the packet must be re-queued, 2 if the packet
+ * is ready to go.
+ */
+static int if_encap6(Slirp *slirp, struct mbuf *ifm, struct ethhdr *eh,
+        uint8_t ethaddr[ETH_ALEN])
+{
+    const struct ip6 *ip6h = mtod(ifm, const struct ip6 *);
+    if (!ndp_table_search(slirp, ip6h->ip_dst, ethaddr)) {
+        if (!ifm->resolution_requested) {
+            ndp_send_ns(slirp, ip6h->ip_dst);
+            ifm->resolution_requested = true;
+            ifm->expiration_date =
+                qemu_clock_get_ns(QEMU_CLOCK_REALTIME) + 1000000000ULL;
+        }
+        return 0;
+    } else {
+        eh->h_proto = htons(ETH_P_IPV6);
+        in6_compute_ethaddr(ip6h->ip_src, eh->h_source);
+
+        /* Send this */
+        return 2;
+    }
+}
+
 /* Output the IP packet to the ethernet device. Returns 0 if the packet must be
  * re-queued.
  */
@@ -849,9 +888,15 @@ int if_encap(Slirp *slirp, struct mbuf *ifm)
         }
         break;
 
+    case IP6VERSION:
+        ret = if_encap6(slirp, ifm, eh, ethaddr);
+        if (ret < 2) {
+            return ret;
+        }
+        break;
+
     default:
-        /* Do not assert while we don't manage IP6VERSION */
-        /* assert(0); */
+        g_assert_not_reached();
         break;
     }
 
diff --git a/slirp/slirp.h b/slirp/slirp.h
index 239fe29..15775bc 100644
--- a/slirp/slirp.h
+++ b/slirp/slirp.h
@@ -131,6 +131,8 @@ void free(void *ptr);
 #include <sys/stropts.h>
 #endif
 
+#include <glib.h>
+
 #include "debug.h"
 
 #include "qemu/queue.h"
@@ -139,12 +141,14 @@ void free(void *ptr);
 
 #include "libslirp.h"
 #include "ip.h"
+#include "ip6.h"
 #include "tcp.h"
 #include "tcp_timer.h"
 #include "tcp_var.h"
 #include "tcpip.h"
 #include "udp.h"
 #include "ip_icmp.h"
+#include "ip6_icmp.h"
 #include "mbuf.h"
 #include "sbuf.h"
 #include "socket.h"
@@ -196,6 +200,23 @@ void arp_table_add(Slirp *slirp, uint32_t ip_addr, uint8_t ethaddr[ETH_ALEN]);
 bool arp_table_search(Slirp *slirp, uint32_t ip_addr,
                       uint8_t out_ethaddr[ETH_ALEN]);
 
+struct ndpentry {
+    unsigned char   eth_addr[ETH_ALEN];     /* sender hardware address */
+    struct in6_addr ip_addr;                /* sender IP address       */
+} QEMU_PACKED;
+
+#define NDP_TABLE_SIZE 16
+
+typedef struct NdpTable {
+    struct ndpentry table[NDP_TABLE_SIZE];
+    int next_victim;
+} NdpTable;
+
+void ndp_table_add(Slirp *slirp, struct in6_addr ip_addr,
+                   uint8_t ethaddr[ETH_ALEN]);
+bool ndp_table_search(Slirp *slirp, struct in6_addr ip_addr,
+                      uint8_t out_ethaddr[ETH_ALEN]);
+
 struct Slirp {
     QTAILQ_ENTRY(Slirp) entry;
     u_int time_fasttimo;
@@ -206,6 +227,9 @@ struct Slirp {
     struct in_addr vnetwork_addr;
     struct in_addr vnetwork_mask;
     struct in_addr vhost_addr;
+    struct in6_addr vprefix_addr6;
+    uint8_t vprefix_len;
+    struct in6_addr vhost_addr6;
     struct in_addr vdhcp_startaddr;
     struct in_addr vnameserver_addr;
 
@@ -254,6 +278,10 @@ struct Slirp {
     struct tftp_session tftp_sessions[TFTP_SESSIONS_MAX];
 
     ArpTable arp_table;
+    NdpTable ndp_table;
+
+    GRand *grand;
+    QEMUTimer *ra_timer;
 
     void *opaque;
 };
@@ -296,6 +324,7 @@ int translate_dnssearch(Slirp *s, const char ** names);
 
 /* cksum.c */
 int cksum(struct mbuf *m, int len);
+int ip6_cksum(struct mbuf *m);
 
 /* if.c */
 void if_init(Slirp *);
@@ -311,6 +340,14 @@ void ip_stripoptions(register struct mbuf *, struct mbuf *);
 /* ip_output.c */
 int ip_output(struct socket *, struct mbuf *);
 
+/* ip6_input.c */
+void ip6_init(Slirp *);
+void ip6_cleanup(Slirp *);
+void ip6_input(struct mbuf *);
+
+/* ip6_output */
+int ip6_output(struct socket *, struct mbuf *, int fast);
+
 /* tcp_input.c */
 void tcp_input(register struct mbuf *, int, struct socket *);
 int tcp_mss(register struct tcpcb *, u_int);
diff --git a/slirp/socket.h b/slirp/socket.h
index c4afc94..bcebce1 100644
--- a/slirp/socket.h
+++ b/slirp/socket.h
@@ -102,6 +102,13 @@ static inline int sockaddr_equal(struct sockaddr_storage *a,
         return a4->sin_addr.s_addr == b4->sin_addr.s_addr
                && a4->sin_port == b4->sin_port;
     }
+    case AF_INET6:
+    {
+        struct sockaddr_in6 *a6 = (struct sockaddr_in6 *) a;
+        struct sockaddr_in6 *b6 = (struct sockaddr_in6 *) b;
+        return (in6_equal(&a6->sin6_addr, &b6->sin6_addr)
+                && a6->sin6_port == b6->sin6_port);
+    }
     default:
         g_assert_not_reached();
     }
-- 
2.7.0

^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [Qemu-devel] [PATCHv9 02/10] slirp: Adding ICMPv6 error sending
  2016-02-22 19:28 [Qemu-devel] [PATCHv9 0/10] slirp: Adding IPv6 support to Qemu -net user mode Samuel Thibault
  2016-02-22 19:28 ` [Qemu-devel] [PATCHv9 01/10] slirp: Adding IPv6, ICMPv6 Echo and NDP autoconfiguration Samuel Thibault
@ 2016-02-22 19:28 ` Samuel Thibault
  2016-03-07  6:55   ` Jason Wang
  2016-02-22 19:28 ` [Qemu-devel] [PATCHv9 03/10] slirp: Adding IPv6 UDP support Samuel Thibault
                   ` (9 subsequent siblings)
  11 siblings, 1 reply; 51+ messages in thread
From: Samuel Thibault @ 2016-02-22 19:28 UTC (permalink / raw)
  To: qemu-devel
  Cc: Thomas Huth, zhanghailiang, Li Zhijian, Stefan Hajnoczi,
	Jason Wang, Dave Gilbert, Vasiliy Tolstov, Huangpeng,
	Yann Bordenave, Gonglei, Jan Kiszka, Samuel Thibault,
	Guillaume Subiron

From: Yann Bordenave <meow@meowstars.org>

Disambiguation : icmp_error is renamed into icmp_send_error, since it
doesn't manage errors, but only sends ICMP Error messages.

Adding icmp6_send_error to send ICMPv6 Error messages. This function is
simpler than the v4 version.
Adding some calls in various functions to send ICMP errors, when a
received packet is too big, or when its hop limit is 0.

Signed-off-by: Yann Bordenave <meow@meowstars.org>
Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
Reviewed-by: Thomas Huth <thuth@redhat.com>
---
 slirp/ip6_icmp.c  | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 slirp/ip6_icmp.h  | 10 +++++++++
 slirp/ip6_input.c | 13 ++++++-----
 slirp/ip_icmp.c   | 12 +++++------
 slirp/ip_icmp.h   |  4 ++--
 slirp/ip_input.c  |  8 +++----
 slirp/socket.c    |  4 ++--
 slirp/tcp_input.c |  2 +-
 slirp/udp.c       |  3 ++-
 9 files changed, 99 insertions(+), 21 deletions(-)

diff --git a/slirp/ip6_icmp.c b/slirp/ip6_icmp.c
index 029d297..1cc65db 100644
--- a/slirp/ip6_icmp.c
+++ b/slirp/ip6_icmp.c
@@ -59,6 +59,70 @@ static void icmp6_send_echoreply(struct mbuf *m, Slirp *slirp, struct ip6 *ip,
     ip6_output(NULL, t, 0);
 }
 
+void icmp6_send_error(struct mbuf *m, uint8_t type, uint8_t code)
+{
+    Slirp *slirp = m->slirp;
+    struct mbuf *t;
+    struct ip6 *ip = mtod(m, struct ip6 *);
+
+    char addrstr[INET6_ADDRSTRLEN];
+    DEBUG_CALL("icmp_send_error");
+    DEBUG_ARGS((dfd, " type = %d, code = %d\n", type, code));
+
+    if (IN6_IS_ADDR_MULTICAST(&ip->ip_src) ||
+            IN6_IS_ADDR_UNSPECIFIED(&ip->ip_src)) {
+        /* TODO icmp error? */
+        return;
+    }
+
+    t = m_get(slirp);
+
+    /* IPv6 packet */
+    struct ip6 *rip = mtod(t, struct ip6 *);
+    rip->ip_src = (struct in6_addr)LINKLOCAL_ADDR;
+    rip->ip_dst = ip->ip_src;
+    inet_ntop(AF_INET6, &rip->ip_dst, addrstr, INET6_ADDRSTRLEN);
+    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));
+    rip->ip_pl = htons(ICMP6_ERROR_MINLEN + error_data_len);
+    t->m_len = sizeof(struct ip6) + ntohs(rip->ip_pl);
+
+    /* ICMPv6 packet */
+    t->m_data += sizeof(struct ip6);
+    struct icmp6 *ricmp = mtod(t, struct icmp6 *);
+    ricmp->icmp6_type = type;
+    ricmp->icmp6_code = code;
+    ricmp->icmp6_cksum = 0;
+
+    switch (type) {
+    case ICMP6_UNREACH:
+    case ICMP6_TIMXCEED:
+        ricmp->icmp6_err.unused = 0;
+        break;
+    case ICMP6_TOOBIG:
+        ricmp->icmp6_err.mtu = htonl(IF_MTU);
+        break;
+    case ICMP6_PARAMPROB:
+        /* TODO: Handle this case */
+        break;
+    default:
+        g_assert_not_reached();
+        break;
+    }
+    t->m_data += ICMP6_ERROR_MINLEN;
+    memcpy(t->m_data, m->m_data, error_data_len);
+
+    /* Checksum */
+    t->m_data -= ICMP6_ERROR_MINLEN;
+    t->m_data -= sizeof(struct ip6);
+    ricmp->icmp6_cksum = ip6_cksum(t);
+
+    ip6_output(NULL, t, 0);
+}
+
 /*
  * Send NDP Router Advertisement
  */
diff --git a/slirp/ip6_icmp.h b/slirp/ip6_icmp.h
index b2c40d6..9460bf8 100644
--- a/slirp/ip6_icmp.h
+++ b/slirp/ip6_icmp.h
@@ -19,6 +19,12 @@ struct icmp6_echo { /* Echo Messages */
     uint16_t seq_num;
 };
 
+union icmp6_error_body {
+    uint32_t unused;
+    uint32_t pointer;
+    uint32_t mtu;
+};
+
 /*
  * NDP Messages
  */
@@ -82,6 +88,7 @@ struct icmp6 {
     uint8_t     icmp6_code;         /* type sub code */
     uint16_t    icmp6_cksum;        /* ones complement cksum of struct */
     union {
+        union icmp6_error_body error_body;
         struct icmp6_echo echo;
         struct ndp_rs ndp_rs;
         struct ndp_ra ndp_ra;
@@ -89,6 +96,7 @@ struct icmp6 {
         struct ndp_na ndp_na;
         struct ndp_redirect ndp_redirect;
     } icmp6_body;
+#define icmp6_err icmp6_body.error_body
 #define icmp6_echo icmp6_body.echo
 #define icmp6_nrs icmp6_body.ndp_rs
 #define icmp6_nra icmp6_body.ndp_ra
@@ -98,6 +106,7 @@ struct icmp6 {
 } QEMU_PACKED;
 
 #define ICMP6_MINLEN    4
+#define ICMP6_ERROR_MINLEN  8
 #define ICMP6_ECHO_MINLEN   8
 #define ICMP6_NDP_RS_MINLEN 8
 #define ICMP6_NDP_RA_MINLEN 16
@@ -197,6 +206,7 @@ struct ndpopt {
 void icmp6_init(Slirp *slirp);
 void icmp6_cleanup(Slirp *slirp);
 void icmp6_input(struct mbuf *);
+void icmp6_send_error(struct mbuf *m, uint8_t type, uint8_t code);
 void ndp_send_ra(Slirp *slirp);
 void ndp_send_ns(Slirp *slirp, struct in6_addr addr);
 
diff --git a/slirp/ip6_input.c b/slirp/ip6_input.c
index df249f1..b6a438d 100644
--- a/slirp/ip6_input.c
+++ b/slirp/ip6_input.c
@@ -39,9 +39,14 @@ void ip6_input(struct mbuf *m)
         goto bad;
     }
 
+    if (ntohs(ip6->ip_pl) > IF_MTU) {
+        icmp6_send_error(m, ICMP6_TOOBIG, 0);
+        goto bad;
+    }
+
     /* check ip_ttl for a correct ICMP reply */
     if (ip6->ip_hl == 0) {
-        /*icmp_error(m, ICMP_TIMXCEED,ICMP_TIMXCEED_INTRANS, 0,"ttl");*/
+        icmp6_send_error(m, ICMP6_TIMXCEED, ICMP6_TIMXCEED_INTRANS);
         goto bad;
     }
 
@@ -49,14 +54,12 @@ void ip6_input(struct mbuf *m)
      * Switch out to protocol's input routine.
      */
     switch (ip6->ip_nh) {
-#if 0
     case IPPROTO_TCP:
-        tcp_input(m, hlen, (struct socket *)NULL);
+        icmp6_send_error(m, ICMP6_UNREACH, ICMP6_UNREACH_NO_ROUTE);
         break;
     case IPPROTO_UDP:
-        udp_input(m, hlen);
+        icmp6_send_error(m, ICMP6_UNREACH, ICMP6_UNREACH_NO_ROUTE);
         break;
-#endif
     case IPPROTO_ICMPV6:
         icmp6_input(m);
         break;
diff --git a/slirp/ip_icmp.c b/slirp/ip_icmp.c
index ace3982..590dada 100644
--- a/slirp/ip_icmp.c
+++ b/slirp/ip_icmp.c
@@ -38,7 +38,7 @@
 /* Be nice and tell them it's just a pseudo-ping packet */
 static const char icmp_ping_msg[] = "This is a pseudo-PING packet used by Slirp to emulate ICMP ECHO-REQUEST packets.\n";
 
-/* list of actions for icmp_error() on RX of an icmp message */
+/* list of actions for icmp_send_error() on RX of an icmp message */
 static const int icmp_flush[19] = {
 /*  ECHO REPLY (0)  */   0,
 		         1,
@@ -101,7 +101,7 @@ static int icmp_send(struct socket *so, struct mbuf *m, int hlen)
                (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_send_error(m, ICMP_UNREACH, ICMP_UNREACH_NET, 0, strerror(errno));
         icmp_detach(so);
     }
 
@@ -189,7 +189,7 @@ icmp_input(struct mbuf *m, int hlen)
 		(struct sockaddr *)&addr, sizeof(addr)) == -1) {
 	DEBUG_MISC((dfd,"icmp_input udp sendto tx errno = %d-%s\n",
 		    errno,strerror(errno)));
-	icmp_error(m, ICMP_UNREACH,ICMP_UNREACH_NET, 0,strerror(errno));
+	icmp_send_error(m, ICMP_UNREACH, ICMP_UNREACH_NET, 0, strerror(errno));
 	udp_detach(so);
       }
     } /* if ip->ip_dst.s_addr == alias_addr.s_addr */
@@ -235,7 +235,7 @@ end_error:
 
 #define ICMP_MAXDATALEN (IP_MSS-28)
 void
-icmp_error(struct mbuf *msrc, u_char type, u_char code, int minsize,
+icmp_send_error(struct mbuf *msrc, u_char type, u_char code, int minsize,
            const char *message)
 {
   unsigned hlen, shlen, s_ip_len;
@@ -243,7 +243,7 @@ icmp_error(struct mbuf *msrc, u_char type, u_char code, int minsize,
   register struct icmp *icp;
   register struct mbuf *m;
 
-  DEBUG_CALL("icmp_error");
+  DEBUG_CALL("icmp_send_error");
   DEBUG_ARG("msrc = %p", msrc);
   DEBUG_ARG("msrc_len = %d", msrc->m_len);
 
@@ -433,7 +433,7 @@ void icmp_receive(struct socket *so)
         }
         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));
+        icmp_send_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! */
diff --git a/slirp/ip_icmp.h b/slirp/ip_icmp.h
index be4426b..846761d 100644
--- a/slirp/ip_icmp.h
+++ b/slirp/ip_icmp.h
@@ -156,8 +156,8 @@ struct icmp {
 void icmp_init(Slirp *slirp);
 void icmp_cleanup(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_send_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);
diff --git a/slirp/ip_input.c b/slirp/ip_input.c
index e4855ae..16fb2cb 100644
--- a/slirp/ip_input.c
+++ b/slirp/ip_input.c
@@ -132,9 +132,9 @@ ip_input(struct mbuf *m)
 	   m_adj(m, ip->ip_len - m->m_len);
 
 	/* check ip_ttl for a correct ICMP reply */
-	if(ip->ip_ttl==0) {
-	  icmp_error(m, ICMP_TIMXCEED,ICMP_TIMXCEED_INTRANS, 0,"ttl");
-	  goto bad;
+	if (ip->ip_ttl == 0) {
+	    icmp_send_error(m, ICMP_TIMXCEED, ICMP_TIMXCEED_INTRANS, 0, "ttl");
+	    goto bad;
 	}
 
 	/*
@@ -637,7 +637,7 @@ typedef uint32_t n_time;
 	}
 	return (0);
 bad:
- 	icmp_error(m, type, code, 0, 0);
+	icmp_send_error(m, type, code, 0, 0);
 
 	return (1);
 }
diff --git a/slirp/socket.c b/slirp/socket.c
index 2b5453e..32b1ba3 100644
--- a/slirp/socket.c
+++ b/slirp/socket.c
@@ -463,7 +463,7 @@ sorecvfrom(struct socket *so)
 
 	    DEBUG_MISC((dfd," udp icmp rx errno = %d-%s\n",
 			errno,strerror(errno)));
-	    icmp_error(so->so_m, ICMP_UNREACH,code, 0,strerror(errno));
+	    icmp_send_error(so->so_m, ICMP_UNREACH, code, 0, strerror(errno));
 	  } else {
 	    icmp_reflect(so->so_m);
             so->so_m = NULL; /* Don't m_free() it again! */
@@ -511,7 +511,7 @@ sorecvfrom(struct socket *so)
 	    else if(errno == ENETUNREACH) code=ICMP_UNREACH_NET;
 
 	    DEBUG_MISC((dfd," rx error, tx icmp ICMP_UNREACH:%i\n", code));
-	    icmp_error(so->so_m, ICMP_UNREACH,code, 0,strerror(errno));
+	    icmp_send_error(so->so_m, ICMP_UNREACH, code, 0, strerror(errno));
 	    m_free(m);
 	  } else {
 	  /*
diff --git a/slirp/tcp_input.c b/slirp/tcp_input.c
index 2027a75..5f845da 100644
--- a/slirp/tcp_input.c
+++ b/slirp/tcp_input.c
@@ -608,7 +608,7 @@ findso:
 	      m->m_data -= sizeof(struct tcpiphdr)+off-sizeof(struct tcphdr);
 	      m->m_len  += sizeof(struct tcpiphdr)+off-sizeof(struct tcphdr);
 	      *ip=save_ip;
-	      icmp_error(m, ICMP_UNREACH,code, 0,strerror(errno));
+	      icmp_send_error(m, ICMP_UNREACH, code, 0, strerror(errno));
 	    }
             tcp_close(tp);
 	    m_free(m);
diff --git a/slirp/udp.c b/slirp/udp.c
index 6b39cab..be012fb 100644
--- a/slirp/udp.c
+++ b/slirp/udp.c
@@ -209,7 +209,8 @@ udp_input(register struct mbuf *m, int iphlen)
 	  m->m_data -= iphlen;
 	  *ip=save_ip;
 	  DEBUG_MISC((dfd,"udp tx errno = %d-%s\n",errno,strerror(errno)));
-	  icmp_error(m, ICMP_UNREACH,ICMP_UNREACH_NET, 0,strerror(errno));
+	  icmp_send_error(m, ICMP_UNREACH, ICMP_UNREACH_NET, 0,
+	                  strerror(errno));
 	  goto bad;
 	}
 
-- 
2.7.0

^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [Qemu-devel] [PATCHv9 03/10] slirp: Adding IPv6 UDP support
  2016-02-22 19:28 [Qemu-devel] [PATCHv9 0/10] slirp: Adding IPv6 support to Qemu -net user mode Samuel Thibault
  2016-02-22 19:28 ` [Qemu-devel] [PATCHv9 01/10] slirp: Adding IPv6, ICMPv6 Echo and NDP autoconfiguration Samuel Thibault
  2016-02-22 19:28 ` [Qemu-devel] [PATCHv9 02/10] slirp: Adding ICMPv6 error sending Samuel Thibault
@ 2016-02-22 19:28 ` Samuel Thibault
  2016-03-07  6:57   ` Jason Wang
  2016-02-22 19:28 ` [Qemu-devel] [PATCHv9 04/10] slirp: Factorizing tcpiphdr structure with an union Samuel Thibault
                   ` (8 subsequent siblings)
  11 siblings, 1 reply; 51+ messages in thread
From: Samuel Thibault @ 2016-02-22 19:28 UTC (permalink / raw)
  To: qemu-devel
  Cc: Thomas Huth, zhanghailiang, Li Zhijian, Stefan Hajnoczi,
	Jason Wang, Dave Gilbert, Vasiliy Tolstov, Huangpeng, Gonglei,
	Jan Kiszka, Samuel Thibault, Guillaume Subiron

From: Guillaume Subiron <maethor@subiron.org>

This adds the sin6 case in the fhost and lhost unions and related macros.
It adds udp6_input() and udp6_output().
It adds the IPv6 case in sorecvfrom().
Finally, udp_input() is called by ip6_input().

Signed-off-by: Guillaume Subiron <maethor@subiron.org>
Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
Reviewed-by: Thomas Huth <thuth@redhat.com>
---
 slirp/Makefile.objs |   2 +-
 slirp/ip6_input.c   |   2 +-
 slirp/socket.c      |   5 ++
 slirp/socket.h      |   6 ++
 slirp/udp.h         |   5 ++
 slirp/udp6.c        | 157 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 175 insertions(+), 2 deletions(-)
 create mode 100644 slirp/udp6.c

diff --git a/slirp/Makefile.objs b/slirp/Makefile.objs
index 4e3a289..6748e4f 100644
--- a/slirp/Makefile.objs
+++ b/slirp/Makefile.objs
@@ -1,5 +1,5 @@
 common-obj-y = cksum.o if.o ip_icmp.o ip6_icmp.o ip6_input.o ip6_output.o \
                ip_input.o ip_output.o dnssearch.o
 common-obj-y += slirp.o mbuf.o misc.o sbuf.o socket.o tcp_input.o tcp_output.o
-common-obj-y += tcp_subr.o tcp_timer.o udp.o bootp.o tftp.o arp_table.o \
+common-obj-y += tcp_subr.o tcp_timer.o udp.o udp6.o bootp.o tftp.o arp_table.o \
                 ndp_table.o
diff --git a/slirp/ip6_input.c b/slirp/ip6_input.c
index b6a438d..9ca6d32 100644
--- a/slirp/ip6_input.c
+++ b/slirp/ip6_input.c
@@ -58,7 +58,7 @@ void ip6_input(struct mbuf *m)
         icmp6_send_error(m, ICMP6_UNREACH, ICMP6_UNREACH_NO_ROUTE);
         break;
     case IPPROTO_UDP:
-        icmp6_send_error(m, ICMP6_UNREACH, ICMP6_UNREACH_NO_ROUTE);
+        udp6_input(m);
         break;
     case IPPROTO_ICMPV6:
         icmp6_input(m);
diff --git a/slirp/socket.c b/slirp/socket.c
index 32b1ba3..b79ddec 100644
--- a/slirp/socket.c
+++ b/slirp/socket.c
@@ -541,7 +541,12 @@ sorecvfrom(struct socket *so)
 	                   (struct sockaddr_in *) &daddr,
 	                   so->so_iptos);
 	        break;
+	    case AF_INET6:
+	        udp6_output(so, m, (struct sockaddr_in6 *) &saddr,
+	                    (struct sockaddr_in6 *) &daddr);
+	        break;
 	    default:
+	        g_assert_not_reached();
 	        break;
 	    }
 	  } /* rx error */
diff --git a/slirp/socket.h b/slirp/socket.h
index bcebce1..e9c9b05 100644
--- a/slirp/socket.h
+++ b/slirp/socket.h
@@ -34,17 +34,23 @@ struct socket {
   union {   /* foreign host */
       struct sockaddr_storage ss;
       struct sockaddr_in sin;
+      struct sockaddr_in6 sin6;
   } fhost;
 #define so_faddr fhost.sin.sin_addr
 #define so_fport fhost.sin.sin_port
+#define so_faddr6 fhost.sin6.sin6_addr
+#define so_fport6 fhost.sin6.sin6_port
 #define so_ffamily fhost.ss.ss_family
 
   union {   /* local host */
       struct sockaddr_storage ss;
       struct sockaddr_in sin;
+      struct sockaddr_in6 sin6;
   } lhost;
 #define so_laddr lhost.sin.sin_addr
 #define so_lport lhost.sin.sin_port
+#define so_laddr6 lhost.sin6.sin6_addr
+#define so_lport6 lhost.sin6.sin6_port
 #define so_lfamily lhost.ss.ss_family
 
   uint8_t	so_iptos;	/* Type of service */
diff --git a/slirp/udp.h b/slirp/udp.h
index 2f9de38..10cc780 100644
--- a/slirp/udp.h
+++ b/slirp/udp.h
@@ -83,4 +83,9 @@ struct socket * udp_listen(Slirp *, uint32_t, u_int, uint32_t, u_int,
 int udp_output(struct socket *so, struct mbuf *m,
                 struct sockaddr_in *saddr, struct sockaddr_in *daddr,
                 int iptos);
+
+void udp6_input(register struct mbuf *);
+int udp6_output(struct socket *so, struct mbuf *m,
+                struct sockaddr_in6 *saddr, struct sockaddr_in6 *daddr);
+
 #endif
diff --git a/slirp/udp6.c b/slirp/udp6.c
new file mode 100644
index 0000000..8952de2
--- /dev/null
+++ b/slirp/udp6.c
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 2013
+ * Guillaume Subiron
+ */
+
+#include "slirp.h"
+#include "qemu/osdep.h"
+#include "udp.h"
+
+void udp6_input(struct mbuf *m)
+{
+    Slirp *slirp = m->slirp;
+    struct ip6 *ip, save_ip;
+    struct udphdr *uh;
+    int hlen = sizeof(struct ip6);
+    int len;
+    struct socket *so;
+    struct sockaddr_in6 lhost;
+
+    DEBUG_CALL("udp6_input");
+    DEBUG_ARG("m = %lx", (long)m);
+
+    if (slirp->restricted) {
+        goto bad;
+    }
+
+    ip = mtod(m, struct ip6 *);
+    m->m_len -= hlen;
+    m->m_data += hlen;
+    uh = mtod(m, struct udphdr *);
+    m->m_len += hlen;
+    m->m_data -= hlen;
+
+    if (ip6_cksum(m)) {
+        goto bad;
+    }
+
+    len = ntohs((uint16_t)uh->uh_ulen);
+
+    /*
+     * Make mbuf data length reflect UDP length.
+     * If not enough data to reflect UDP length, drop.
+     */
+    if (ntohs(ip->ip_pl) != len) {
+        if (len > ntohs(ip->ip_pl)) {
+            goto bad;
+        }
+        m_adj(m, len - ntohs(ip->ip_pl));
+        ip->ip_pl = htons(len);
+    }
+
+    /*
+     * Save a copy of the IP header in case we want restore it
+     * for sending an ICMP error message in response.
+     */
+    save_ip = *ip;
+
+    /* TODO handle DHCP/BOOTP */
+    /* TODO handle TFTP */
+
+    /* Locate pcb for datagram. */
+    lhost.sin6_family = AF_INET6;
+    lhost.sin6_addr = ip->ip_src;
+    lhost.sin6_port = uh->uh_sport;
+
+    so = solookup(&slirp->udp_last_so, &slirp->udb,
+                  (struct sockaddr_storage *) &lhost, NULL);
+
+    if (so == NULL) {
+        /* If there's no socket for this packet, create one. */
+        so = socreate(slirp);
+        if (!so) {
+            goto bad;
+        }
+        if (udp_attach(so, AF_INET6) == -1) {
+            DEBUG_MISC((dfd, " udp6_attach errno = %d-%s\n",
+                        errno, strerror(errno)));
+            sofree(so);
+            goto bad;
+        }
+
+        /* Setup fields */
+        so->so_lfamily = AF_INET6;
+        so->so_laddr6 = ip->ip_src;
+        so->so_lport6 = uh->uh_sport;
+    }
+
+    so->so_ffamily = AF_INET6;
+    so->so_faddr6 = ip->ip_dst; /* XXX */
+    so->so_fport6 = uh->uh_dport; /* XXX */
+
+    hlen += sizeof(struct udphdr);
+    m->m_len -= hlen;
+    m->m_data += hlen;
+
+    /*
+     * Now we sendto() the packet.
+     */
+    if (sosendto(so, m) == -1) {
+        m->m_len += hlen;
+        m->m_data -= hlen;
+        *ip = save_ip;
+        DEBUG_MISC((dfd, "udp tx errno = %d-%s\n", errno, strerror(errno)));
+        /* TODO: ICMPv6 error */
+        /*icmp_error(m, ICMP_UNREACH,ICMP_UNREACH_NET, 0,strerror(errno));*/
+        goto bad;
+    }
+
+    m_free(so->so_m);   /* used for ICMP if error on sorecvfrom */
+
+    /* restore the orig mbuf packet */
+    m->m_len += hlen;
+    m->m_data -= hlen;
+    *ip = save_ip;
+    so->so_m = m;
+
+    return;
+bad:
+    m_free(m);
+}
+
+int udp6_output(struct socket *so, struct mbuf *m,
+        struct sockaddr_in6 *saddr, struct sockaddr_in6 *daddr)
+{
+    struct ip6 *ip;
+    struct udphdr *uh;
+
+    DEBUG_CALL("udp6_output");
+    DEBUG_ARG("so = %lx", (long)so);
+    DEBUG_ARG("m = %lx", (long)m);
+
+    /* adjust for header */
+    m->m_data -= sizeof(struct udphdr);
+    m->m_len += sizeof(struct udphdr);
+    uh = mtod(m, struct udphdr *);
+    m->m_data -= sizeof(struct ip6);
+    m->m_len += sizeof(struct ip6);
+    ip = mtod(m, struct ip6 *);
+
+    /* Build IP header */
+    ip->ip_pl = htons(m->m_len - sizeof(struct ip6));
+    ip->ip_nh = IPPROTO_UDP;
+    ip->ip_src = saddr->sin6_addr;
+    ip->ip_dst = daddr->sin6_addr;
+
+    /* Build UDP header */
+    uh->uh_sport = saddr->sin6_port;
+    uh->uh_dport = daddr->sin6_port;
+    uh->uh_ulen = ip->ip_pl;
+    uh->uh_sum = 0;
+    uh->uh_sum = ip6_cksum(m);
+    if (uh->uh_sum == 0) {
+        uh->uh_sum = 0xffff;
+    }
+
+    return ip6_output(so, m, 0);
+}
-- 
2.7.0

^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [Qemu-devel] [PATCHv9 04/10] slirp: Factorizing tcpiphdr structure with an union
  2016-02-22 19:28 [Qemu-devel] [PATCHv9 0/10] slirp: Adding IPv6 support to Qemu -net user mode Samuel Thibault
                   ` (2 preceding siblings ...)
  2016-02-22 19:28 ` [Qemu-devel] [PATCHv9 03/10] slirp: Adding IPv6 UDP support Samuel Thibault
@ 2016-02-22 19:28 ` Samuel Thibault
  2016-02-23  8:07   ` Thomas Huth
  2016-02-22 19:28 ` [Qemu-devel] [PATCHv9 05/10] slirp: Generalizing and neutralizing various TCP functions before adding IPv6 stuff Samuel Thibault
                   ` (7 subsequent siblings)
  11 siblings, 1 reply; 51+ messages in thread
From: Samuel Thibault @ 2016-02-22 19:28 UTC (permalink / raw)
  To: qemu-devel
  Cc: Thomas Huth, zhanghailiang, Li Zhijian, Stefan Hajnoczi,
	Jason Wang, Dave Gilbert, Vasiliy Tolstov, Huangpeng, Gonglei,
	Jan Kiszka, Samuel Thibault, Guillaume Subiron

From: Guillaume Subiron <maethor@subiron.org>

This patch factorizes the tcpiphdr structure to put the IPv4 fields in
an union, for addition of version 6 in further patch.
Using some macros, retrocompatibility of the existing code is assured.

This patch also fixes the SLIRP_MSIZE and margin computation in various
functions, and makes them compatible with the new tcpiphdr structure,
whose size will be bigger than sizeof(struct tcphdr) + sizeof(struct ip)

Signed-off-by: Guillaume Subiron <maethor@subiron.org>
Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
---
 slirp/if.h         |  4 ++--
 slirp/mbuf.c       |  4 ++--
 slirp/slirp.c      | 15 ++++++++-------
 slirp/socket.c     | 13 ++++++++++++-
 slirp/tcp_input.c  | 31 ++++++++++++++++++++-----------
 slirp/tcp_output.c | 18 +++++++++++++-----
 slirp/tcp_subr.c   | 31 ++++++++++++++++++++++---------
 slirp/tcpip.h      | 31 +++++++++++++++++++++++--------
 8 files changed, 102 insertions(+), 45 deletions(-)

diff --git a/slirp/if.h b/slirp/if.h
index 3327023..c7a5c57 100644
--- a/slirp/if.h
+++ b/slirp/if.h
@@ -17,7 +17,7 @@
 #define IF_MRU 1500
 #define	IF_COMP IF_AUTOCOMP	/* Flags for compression */
 
-/* 2 for alignment, 14 for ethernet, 40 for TCP/IP */
-#define IF_MAXLINKHDR (2 + 14 + 40)
+/* 2 for alignment, 14 for ethernet */
+#define IF_MAXLINKHDR (2 + ETH_HLEN)
 
 #endif
diff --git a/slirp/mbuf.c b/slirp/mbuf.c
index c959758..d688dd4 100644
--- a/slirp/mbuf.c
+++ b/slirp/mbuf.c
@@ -22,9 +22,9 @@
 
 /*
  * Find a nice value for msize
- * XXX if_maxlinkhdr already in mtu
  */
-#define SLIRP_MSIZE (IF_MTU + IF_MAXLINKHDR + offsetof(struct mbuf, m_dat) + 6)
+#define SLIRP_MSIZE\
+    (offsetof(struct mbuf, m_dat) + IF_MAXLINKHDR + TCPIPHDR_DELTA + IF_MTU)
 
 void
 m_init(Slirp *slirp)
diff --git a/slirp/slirp.c b/slirp/slirp.c
index c986e0b..3e83ede 100644
--- a/slirp/slirp.c
+++ b/slirp/slirp.c
@@ -756,15 +756,16 @@ void slirp_input(Slirp *slirp, const uint8_t *pkt, int pkt_len)
         m = m_get(slirp);
         if (!m)
             return;
-        /* Note: we add to align the IP header */
-        if (M_FREEROOM(m) < pkt_len + 2) {
-            m_inc(m, pkt_len + 2);
+        /* Note: we add 2 to align the IP header on 4 bytes,
+         * and add the margin for the tcpiphdr overhead  */
+        if (M_FREEROOM(m) < pkt_len + TCPIPHDR_DELTA + 2) {
+            m_inc(m, pkt_len + TCPIPHDR_DELTA + 2);
         }
-        m->m_len = pkt_len + 2;
-        memcpy(m->m_data + 2, pkt, pkt_len);
+        m->m_len = pkt_len + TCPIPHDR_DELTA + 2;
+        memcpy(m->m_data + TCPIPHDR_DELTA + 2, pkt, pkt_len);
 
-        m->m_data += 2 + ETH_HLEN;
-        m->m_len -= 2 + ETH_HLEN;
+        m->m_data += TCPIPHDR_DELTA + 2 + ETH_HLEN;
+        m->m_len -= TCPIPHDR_DELTA + 2 + ETH_HLEN;
 
         if (proto == ETH_P_IP) {
             ip_input(m);
diff --git a/slirp/socket.c b/slirp/socket.c
index b79ddec..d4b02c8 100644
--- a/slirp/socket.c
+++ b/slirp/socket.c
@@ -483,7 +483,18 @@ sorecvfrom(struct socket *so)
 	  if (!m) {
 	      return;
 	  }
-	  m->m_data += IF_MAXLINKHDR;
+	  switch (so->so_ffamily) {
+	  case AF_INET:
+	      m->m_data += IF_MAXLINKHDR + sizeof(struct udpiphdr);
+	      break;
+	  case AF_INET6:
+	      m->m_data += IF_MAXLINKHDR + sizeof(struct ip6)
+	                                 + sizeof(struct udphdr);
+	      break;
+	  default:
+	      g_assert_not_reached();
+	      break;
+	  }
 
 	  /*
 	   * XXX Shouldn't FIONREAD packets destined for port 53,
diff --git a/slirp/tcp_input.c b/slirp/tcp_input.c
index 5f845da..a9de7d1 100644
--- a/slirp/tcp_input.c
+++ b/slirp/tcp_input.c
@@ -256,11 +256,6 @@ tcp_input(struct mbuf *m, int iphlen, struct socket *inso)
 	}
 	slirp = m->slirp;
 
-	/*
-	 * Get IP and TCP header together in first mbuf.
-	 * Note: IP leaves IP header in first mbuf.
-	 */
-	ti = mtod(m, struct tcpiphdr *);
 	if (iphlen > sizeof(struct ip )) {
 	  ip_stripoptions(m, (struct mbuf *)0);
 	  iphlen=sizeof(struct ip );
@@ -277,14 +272,28 @@ tcp_input(struct mbuf *m, int iphlen, struct socket *inso)
 	save_ip.ip_len+= iphlen;
 
 	/*
+	 * Get IP and TCP header together in first mbuf.
+	 * Note: IP leaves IP header in first mbuf.
+	 */
+	m->m_data -= sizeof(struct tcpiphdr) - sizeof(struct ip)
+	                                     - sizeof(struct tcphdr);
+	m->m_len += sizeof(struct tcpiphdr) - sizeof(struct ip)
+	                                    - sizeof(struct tcphdr);
+	ti = mtod(m, struct tcpiphdr *);
+
+	/*
 	 * Checksum extended TCP header and data.
 	 */
-	tlen = ((struct ip *)ti)->ip_len;
-        tcpiphdr2qlink(ti)->next = tcpiphdr2qlink(ti)->prev = NULL;
-        memset(&ti->ti_i.ih_mbuf, 0 , sizeof(struct mbuf_ptr));
-	ti->ti_x1 = 0;
+	tlen = ip->ip_len;
+	tcpiphdr2qlink(ti)->next = tcpiphdr2qlink(ti)->prev = NULL;
+	memset(&ti->ih_mbuf, 0 , sizeof(struct mbuf_ptr));
+	memset(&ti->ti, 0, sizeof(ti->ti));
+	ti->ti_x0 = 0;
+	ti->ti_src = save_ip.ip_src;
+	ti->ti_dst = save_ip.ip_dst;
+	ti->ti_pr = save_ip.ip_p;
 	ti->ti_len = htons((uint16_t)tlen);
-	len = sizeof(struct ip ) + tlen;
+	len = ((sizeof(struct tcpiphdr) - sizeof(struct tcphdr)) + tlen);
 	if(cksum(m, len)) {
 	  goto drop;
 	}
@@ -1475,7 +1484,7 @@ tcp_mss(struct tcpcb *tp, u_int offer)
 	DEBUG_ARG("tp = %p", tp);
 	DEBUG_ARG("offer = %d", offer);
 
-	mss = min(IF_MTU, IF_MRU) - sizeof(struct tcpiphdr);
+	mss = min(IF_MTU, IF_MRU) - sizeof(struct tcphdr) + sizeof(struct ip);
 	if (offer)
 		mss = min(mss, offer);
 	mss = max(mss, 32);
diff --git a/slirp/tcp_output.c b/slirp/tcp_output.c
index 34e4d2e..7fc6a87 100644
--- a/slirp/tcp_output.c
+++ b/slirp/tcp_output.c
@@ -448,15 +448,23 @@ send:
 	 */
 	m->m_len = hdrlen + len; /* XXX Needed? m_len should be correct */
 
-    {
+	struct tcpiphdr tcpiph_save = *(mtod(m, struct tcpiphdr *));
+	m->m_data += sizeof(struct tcpiphdr) - sizeof(struct tcphdr)
+	                                     - sizeof(struct ip);
+	m->m_len  -= sizeof(struct tcpiphdr) - sizeof(struct tcphdr)
+	                                     - sizeof(struct ip);
+	struct ip *ip = mtod(m, struct ip *);
 
-	((struct ip *)ti)->ip_len = m->m_len;
+	ip->ip_len = m->m_len;
+	ip->ip_dst = tcpiph_save.ti_dst;
+	ip->ip_src = tcpiph_save.ti_src;
+	ip->ip_p = tcpiph_save.ti_pr;
 
-	((struct ip *)ti)->ip_ttl = IPDEFTTL;
-	((struct ip *)ti)->ip_tos = so->so_iptos;
+	ip->ip_ttl = IPDEFTTL;
+	ip->ip_tos = so->so_iptos;
 
 	error = ip_output(so, m);
-    }
+
 	if (error) {
 out:
 		return (error);
diff --git a/slirp/tcp_subr.c b/slirp/tcp_subr.c
index b1aa1f2..cd021df 100644
--- a/slirp/tcp_subr.c
+++ b/slirp/tcp_subr.c
@@ -76,9 +76,10 @@ tcp_template(struct tcpcb *tp)
 	register struct tcpiphdr *n = &tp->t_template;
 
 	n->ti_mbuf = NULL;
-	n->ti_x1 = 0;
+	memset(&n->ti, 0, sizeof(n->ti));
+	n->ti_x0 = 0;
 	n->ti_pr = IPPROTO_TCP;
-	n->ti_len = htons(sizeof (struct tcpiphdr) - sizeof (struct ip));
+	n->ti_len = htons(sizeof(struct tcphdr));
 	n->ti_src = so->so_faddr;
 	n->ti_dst = so->so_laddr;
 	n->ti_sport = so->so_fport;
@@ -131,6 +132,7 @@ tcp_respond(struct tcpcb *tp, struct tcpiphdr *ti, struct mbuf *m,
 		m->m_data += IF_MAXLINKHDR;
 		*mtod(m, struct tcpiphdr *) = *ti;
 		ti = mtod(m, struct tcpiphdr *);
+		memset(&ti->ti, 0, sizeof(ti->ti));
 		flags = TH_ACK;
 	} else {
 		/*
@@ -150,8 +152,8 @@ tcp_respond(struct tcpcb *tp, struct tcpiphdr *ti, struct mbuf *m,
 	tlen += sizeof (struct tcpiphdr);
 	m->m_len = tlen;
 
-        ti->ti_mbuf = NULL;
-	ti->ti_x1 = 0;
+	ti->ti_mbuf = NULL;
+	ti->ti_x0 = 0;
 	ti->ti_seq = htonl(seq);
 	ti->ti_ack = htonl(ack);
 	ti->ti_x2 = 0;
@@ -164,12 +166,23 @@ tcp_respond(struct tcpcb *tp, struct tcpiphdr *ti, struct mbuf *m,
 	ti->ti_urp = 0;
 	ti->ti_sum = 0;
 	ti->ti_sum = cksum(m, tlen);
-	((struct ip *)ti)->ip_len = tlen;
 
-	if(flags & TH_RST)
-	  ((struct ip *)ti)->ip_ttl = MAXTTL;
-	else
-	  ((struct ip *)ti)->ip_ttl = IPDEFTTL;
+	struct tcpiphdr tcpiph_save = *(mtod(m, struct tcpiphdr *));
+	m->m_data += sizeof(struct tcpiphdr) - sizeof(struct tcphdr)
+	                                     - sizeof(struct ip);
+	m->m_len  -= sizeof(struct tcpiphdr) - sizeof(struct tcphdr)
+	                                     - sizeof(struct ip);
+	struct ip *ip = mtod(m, struct ip *);
+	ip->ip_len = tlen;
+	ip->ip_dst = tcpiph_save.ti_dst;
+	ip->ip_src = tcpiph_save.ti_src;
+	ip->ip_p = tcpiph_save.ti_pr;
+
+	if (flags & TH_RST) {
+		ip->ip_ttl = MAXTTL;
+	} else {
+		ip->ip_ttl = IPDEFTTL;
+	}
 
 	(void) ip_output((struct socket *)0, m);
 }
diff --git a/slirp/tcpip.h b/slirp/tcpip.h
index 7974ce3..3c5d127 100644
--- a/slirp/tcpip.h
+++ b/slirp/tcpip.h
@@ -37,15 +37,23 @@
  * Tcp+ip header, after ip options removed.
  */
 struct tcpiphdr {
-	struct 	ipovly ti_i;		/* overlaid ip structure */
-	struct	tcphdr ti_t;		/* tcp header */
+    struct mbuf_ptr ih_mbuf;	/* backpointer to mbuf */
+    union {
+        struct {
+            struct  in_addr ih_src; /* source internet address */
+            struct  in_addr ih_dst; /* destination internet address */
+            uint8_t ih_x1;          /* (unused) */
+            uint8_t ih_pr;          /* protocol */
+        } ti_i4;
+    } ti;
+    uint16_t    ti_x0;
+    uint16_t    ti_len;             /* protocol length */
+    struct      tcphdr ti_t;        /* tcp header */
 };
-#define	ti_mbuf		ti_i.ih_mbuf.mptr
-#define	ti_x1		ti_i.ih_x1
-#define	ti_pr		ti_i.ih_pr
-#define	ti_len		ti_i.ih_len
-#define	ti_src		ti_i.ih_src
-#define	ti_dst		ti_i.ih_dst
+#define	ti_mbuf		ih_mbuf.mptr
+#define	ti_pr		ti.ti_i4.ih_pr
+#define	ti_src		ti.ti_i4.ih_src
+#define	ti_dst		ti.ti_i4.ih_dst
 #define	ti_sport	ti_t.th_sport
 #define	ti_dport	ti_t.th_dport
 #define	ti_seq		ti_t.th_seq
@@ -65,6 +73,13 @@ struct tcpiphdr {
 #define tcpfrag_list_end(F, T) (tcpiphdr2qlink(F) == (struct qlink*)(T))
 #define tcpfrag_list_empty(T) ((T)->seg_next == (struct tcpiphdr*)(T))
 
+/* This is the difference between the size of a tcpiphdr structure, and the
+ * size of actual ip+tcp headers, rounded up since we need to align data.  */
+#define TCPIPHDR_DELTA\
+    (max(0,\
+         (sizeof(struct tcpiphdr)\
+          - sizeof(struct ip) - sizeof(struct tcphdr) + 3) & ~3))
+
 /*
  * Just a clean way to get to the first byte
  * of the packet
-- 
2.7.0

^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [Qemu-devel] [PATCHv9 05/10] slirp: Generalizing and neutralizing various TCP functions before adding IPv6 stuff
  2016-02-22 19:28 [Qemu-devel] [PATCHv9 0/10] slirp: Adding IPv6 support to Qemu -net user mode Samuel Thibault
                   ` (3 preceding siblings ...)
  2016-02-22 19:28 ` [Qemu-devel] [PATCHv9 04/10] slirp: Factorizing tcpiphdr structure with an union Samuel Thibault
@ 2016-02-22 19:28 ` Samuel Thibault
  2016-02-22 19:28 ` [Qemu-devel] [PATCHv9 06/10] slirp: Reindent after refactoring Samuel Thibault
                   ` (6 subsequent siblings)
  11 siblings, 0 replies; 51+ messages in thread
From: Samuel Thibault @ 2016-02-22 19:28 UTC (permalink / raw)
  To: qemu-devel
  Cc: Thomas Huth, zhanghailiang, Li Zhijian, Stefan Hajnoczi,
	Jason Wang, Dave Gilbert, Vasiliy Tolstov, Huangpeng, Gonglei,
	Jan Kiszka, Samuel Thibault, Guillaume Subiron

From: Guillaume Subiron <maethor@subiron.org>

Basically, this patch adds some switch in various TCP functions to
prepare them for the IPv6 case.

To have something to "switch" in tcp_input() and tcp_respond(), a new
argument is used to give them the sa_family of the addresses they are
working on.

This patch does not include the entailed reindentation, to make proofread
easier. Reindentation is adressed in the following no-op patch.

Signed-off-by: Guillaume Subiron <maethor@subiron.org>
Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
Reviewed-by: Thomas Huth <thuth@redhat.com>
---
 slirp/ip_input.c   |  2 +-
 slirp/slirp.c      |  6 ++++--
 slirp/slirp.h      |  5 +++--
 slirp/tcp_input.c  | 62 ++++++++++++++++++++++++++++++++++++++++++------------
 slirp/tcp_output.c | 14 +++++++++---
 slirp/tcp_subr.c   | 37 +++++++++++++++++++++++++-------
 slirp/tcp_timer.c  |  3 ++-
 7 files changed, 99 insertions(+), 30 deletions(-)

diff --git a/slirp/ip_input.c b/slirp/ip_input.c
index 16fb2cb..12f173d 100644
--- a/slirp/ip_input.c
+++ b/slirp/ip_input.c
@@ -200,7 +200,7 @@ ip_input(struct mbuf *m)
 	 */
 	switch (ip->ip_p) {
 	 case IPPROTO_TCP:
-		tcp_input(m, hlen, (struct socket *)NULL);
+		tcp_input(m, hlen, (struct socket *)NULL, AF_INET);
 		break;
 	 case IPPROTO_UDP:
 		udp_input(m, hlen);
diff --git a/slirp/slirp.c b/slirp/slirp.c
index 3e83ede..d908422 100644
--- a/slirp/slirp.c
+++ b/slirp/slirp.c
@@ -576,7 +576,8 @@ void slirp_pollfds_poll(GArray *pollfds, int select_error)
                         /*
                          * Continue tcp_input
                          */
-                        tcp_input((struct mbuf *)NULL, sizeof(struct ip), so);
+                        tcp_input((struct mbuf *)NULL, sizeof(struct ip), so,
+                                  so->so_ffamily);
                         /* continue; */
                     } else {
                         ret = sowrite(so);
@@ -625,7 +626,8 @@ void slirp_pollfds_poll(GArray *pollfds, int select_error)
                         }
 
                     }
-                    tcp_input((struct mbuf *)NULL, sizeof(struct ip), so);
+                    tcp_input((struct mbuf *)NULL, sizeof(struct ip), so,
+                              so->so_ffamily);
                 } /* SS_ISFCONNECTING */
 #endif
             }
diff --git a/slirp/slirp.h b/slirp/slirp.h
index 15775bc..967d93e 100644
--- a/slirp/slirp.h
+++ b/slirp/slirp.h
@@ -349,7 +349,7 @@ void ip6_input(struct mbuf *);
 int ip6_output(struct socket *, struct mbuf *, int fast);
 
 /* tcp_input.c */
-void tcp_input(register struct mbuf *, int, struct socket *);
+void tcp_input(register struct mbuf *, int, struct socket *, unsigned short af);
 int tcp_mss(register struct tcpcb *, u_int);
 
 /* tcp_output.c */
@@ -360,7 +360,8 @@ void tcp_setpersist(register struct tcpcb *);
 void tcp_init(Slirp *);
 void tcp_cleanup(Slirp *);
 void tcp_template(struct tcpcb *);
-void tcp_respond(struct tcpcb *, register struct tcpiphdr *, register struct mbuf *, tcp_seq, tcp_seq, int);
+void tcp_respond(struct tcpcb *, register struct tcpiphdr *,
+        register struct mbuf *, tcp_seq, tcp_seq, int, unsigned short);
 struct tcpcb * tcp_newtcpcb(struct socket *);
 struct tcpcb * tcp_close(register struct tcpcb *);
 void tcp_sockclosed(struct tcpcb *);
diff --git a/slirp/tcp_input.c b/slirp/tcp_input.c
index a9de7d1..a2f1044 100644
--- a/slirp/tcp_input.c
+++ b/slirp/tcp_input.c
@@ -214,7 +214,7 @@ present:
  * protocol specification dated September, 1981 very closely.
  */
 void
-tcp_input(struct mbuf *m, int iphlen, struct socket *inso)
+tcp_input(struct mbuf *m, int iphlen, struct socket *inso, unsigned short af)
 {
   	struct ip save_ip, *ip;
 	register struct tcpiphdr *ti;
@@ -256,6 +256,8 @@ tcp_input(struct mbuf *m, int iphlen, struct socket *inso)
 	}
 	slirp = m->slirp;
 
+	switch (af) {
+	case AF_INET:
 	if (iphlen > sizeof(struct ip )) {
 	  ip_stripoptions(m, (struct mbuf *)0);
 	  iphlen=sizeof(struct ip );
@@ -297,6 +299,11 @@ tcp_input(struct mbuf *m, int iphlen, struct socket *inso)
 	if(cksum(m, len)) {
 	  goto drop;
 	}
+	break;
+
+	default:
+	    g_assert_not_reached();
+	}
 
 	/*
 	 * Check that TCP offset makes sense,
@@ -332,14 +339,20 @@ tcp_input(struct mbuf *m, int iphlen, struct socket *inso)
 	 * Locate pcb for segment.
 	 */
 findso:
-	lhost.ss_family = AF_INET;
+	lhost.ss_family = af;
+	fhost.ss_family = af;
+	switch (af) {
+	case AF_INET:
 	lhost4 = (struct sockaddr_in *) &lhost;
 	lhost4->sin_addr = ti->ti_src;
 	lhost4->sin_port = ti->ti_sport;
-	fhost.ss_family = AF_INET;
 	fhost4 = (struct sockaddr_in *) &fhost;
 	fhost4->sin_addr = ti->ti_dst;
 	fhost4->sin_port = ti->ti_dport;
+	    break;
+	default:
+	    g_assert_not_reached();
+	}
 
 	so = solookup(&slirp->tcp_last_so, &slirp->tcb, &lhost, &fhost);
 
@@ -389,8 +402,16 @@ findso:
 	  so->lhost.ss = lhost;
 	  so->fhost.ss = fhost;
 
-	  if ((so->so_iptos = tcp_tos(so)) == 0)
-	    so->so_iptos = ((struct ip *)ti)->ip_tos;
+	  so->so_iptos = tcp_tos(so);
+	  if (so->so_iptos == 0) {
+	      switch (af) {
+	      case AF_INET:
+	          so->so_iptos = ((struct ip *)ti)->ip_tos;
+	          break;
+	      default:
+	          g_assert_not_reached();
+	      }
+	  }
 
 	  tp = sototcpcb(so);
 	  tp->t_state = TCPS_LISTEN;
@@ -569,7 +590,8 @@ findso:
 	   * If this is destined for the control address, then flag to
 	   * tcp_ctl once connected, otherwise connect
 	   */
-	  if ((so->so_faddr.s_addr & slirp->vnetwork_mask.s_addr) ==
+	  if (af == AF_INET &&
+	      (so->so_faddr.s_addr & slirp->vnetwork_mask.s_addr) ==
 	      slirp->vnetwork_addr.s_addr) {
 	    if (so->so_faddr.s_addr != slirp->vhost_addr.s_addr &&
 		so->so_faddr.s_addr != slirp->vnameserver_addr.s_addr) {
@@ -606,8 +628,8 @@ findso:
 			errno,strerror(errno)));
 	    if(errno == ECONNREFUSED) {
 	      /* ACK the SYN, send RST to refuse the connection */
-	      tcp_respond(tp, ti, m, ti->ti_seq+1, (tcp_seq)0,
-			  TH_RST|TH_ACK);
+	      tcp_respond(tp, ti, m, ti->ti_seq + 1, (tcp_seq) 0,
+			  TH_RST | TH_ACK, af);
 	    } else {
 	      if(errno == EHOSTUNREACH) code=ICMP_UNREACH_HOST;
 	      HTONL(ti->ti_seq);             /* restore tcp header */
@@ -616,7 +638,13 @@ findso:
 	      HTONS(ti->ti_urp);
 	      m->m_data -= sizeof(struct tcpiphdr)+off-sizeof(struct tcphdr);
 	      m->m_len  += sizeof(struct tcpiphdr)+off-sizeof(struct tcphdr);
-	      *ip=save_ip;
+	      switch (af) {
+	      case AF_INET:
+	          *ip = save_ip;
+	          break;
+	      default:
+	          g_assert_not_reached();
+	      }
 	      icmp_send_error(m, ICMP_UNREACH, code, 0, strerror(errno));
 	    }
             tcp_close(tp);
@@ -1289,11 +1317,11 @@ dropafterack:
 dropwithreset:
 	/* reuses m if m!=NULL, m_free() unnecessary */
 	if (tiflags & TH_ACK)
-		tcp_respond(tp, ti, m, (tcp_seq)0, ti->ti_ack, TH_RST);
+		tcp_respond(tp, ti, m, (tcp_seq)0, ti->ti_ack, TH_RST, af);
 	else {
 		if (tiflags & TH_SYN) ti->ti_len++;
-		tcp_respond(tp, ti, m, ti->ti_seq+ti->ti_len, (tcp_seq)0,
-		    TH_RST|TH_ACK);
+		tcp_respond(tp, ti, m, ti->ti_seq + ti->ti_len, (tcp_seq) 0,
+		    TH_RST | TH_ACK, af);
 	}
 
 	return;
@@ -1484,7 +1512,15 @@ tcp_mss(struct tcpcb *tp, u_int offer)
 	DEBUG_ARG("tp = %p", tp);
 	DEBUG_ARG("offer = %d", offer);
 
-	mss = min(IF_MTU, IF_MRU) - sizeof(struct tcphdr) + sizeof(struct ip);
+	switch (so->so_ffamily) {
+	case AF_INET:
+	    mss = min(IF_MTU, IF_MRU) - sizeof(struct tcphdr)
+	                              + sizeof(struct ip);
+	    break;
+	default:
+	    g_assert_not_reached();
+	}
+
 	if (offer)
 		mss = min(mss, offer);
 	mss = max(mss, 32);
diff --git a/slirp/tcp_output.c b/slirp/tcp_output.c
index 7fc6a87..32201fb 100644
--- a/slirp/tcp_output.c
+++ b/slirp/tcp_output.c
@@ -61,7 +61,8 @@ tcp_output(struct tcpcb *tp)
 	register long len, win;
 	int off, flags, error;
 	register struct mbuf *m;
-	register struct tcpiphdr *ti;
+	register struct tcpiphdr *ti, tcpiph_save;
+	struct ip *ip;
 	u_char opt[MAX_TCPOPTLEN];
 	unsigned optlen, hdrlen;
 	int idle, sendalot;
@@ -447,13 +448,15 @@ send:
 	 * the template, but need a way to checksum without them.
 	 */
 	m->m_len = hdrlen + len; /* XXX Needed? m_len should be correct */
+	tcpiph_save = *mtod(m, struct tcpiphdr *);
 
-	struct tcpiphdr tcpiph_save = *(mtod(m, struct tcpiphdr *));
+	switch (so->so_ffamily) {
+	case AF_INET:
 	m->m_data += sizeof(struct tcpiphdr) - sizeof(struct tcphdr)
 	                                     - sizeof(struct ip);
 	m->m_len  -= sizeof(struct tcpiphdr) - sizeof(struct tcphdr)
 	                                     - sizeof(struct ip);
-	struct ip *ip = mtod(m, struct ip *);
+	ip = mtod(m, struct ip *);
 
 	ip->ip_len = m->m_len;
 	ip->ip_dst = tcpiph_save.ti_dst;
@@ -464,6 +467,11 @@ send:
 	ip->ip_tos = so->so_iptos;
 
 	error = ip_output(so, m);
+	    break;
+
+	default:
+	    g_assert_not_reached();
+	}
 
 	if (error) {
 out:
diff --git a/slirp/tcp_subr.c b/slirp/tcp_subr.c
index cd021df..ee101e2 100644
--- a/slirp/tcp_subr.c
+++ b/slirp/tcp_subr.c
@@ -78,12 +78,19 @@ tcp_template(struct tcpcb *tp)
 	n->ti_mbuf = NULL;
 	memset(&n->ti, 0, sizeof(n->ti));
 	n->ti_x0 = 0;
+	switch (so->so_ffamily) {
+	case AF_INET:
 	n->ti_pr = IPPROTO_TCP;
 	n->ti_len = htons(sizeof(struct tcphdr));
 	n->ti_src = so->so_faddr;
 	n->ti_dst = so->so_laddr;
 	n->ti_sport = so->so_fport;
 	n->ti_dport = so->so_lport;
+	    break;
+
+	default:
+	    g_assert_not_reached();
+	}
 
 	n->ti_seq = 0;
 	n->ti_ack = 0;
@@ -110,7 +117,7 @@ tcp_template(struct tcpcb *tp)
  */
 void
 tcp_respond(struct tcpcb *tp, struct tcpiphdr *ti, struct mbuf *m,
-            tcp_seq ack, tcp_seq seq, int flags)
+            tcp_seq ack, tcp_seq seq, int flags, unsigned short af)
 {
 	register int tlen;
 	int win = 0;
@@ -144,8 +151,14 @@ tcp_respond(struct tcpcb *tp, struct tcpiphdr *ti, struct mbuf *m,
 		m->m_len = sizeof (struct tcpiphdr);
 		tlen = 0;
 #define xchg(a,b,type) { type t; t=a; a=b; b=t; }
+		switch (af) {
+		case AF_INET:
 		xchg(ti->ti_dst.s_addr, ti->ti_src.s_addr, uint32_t);
 		xchg(ti->ti_dport, ti->ti_sport, uint16_t);
+		    break;
+		default:
+		    g_assert_not_reached();
+		}
 #undef xchg
 	}
 	ti->ti_len = htons((u_short)(sizeof (struct tcphdr) + tlen));
@@ -168,11 +181,15 @@ tcp_respond(struct tcpcb *tp, struct tcpiphdr *ti, struct mbuf *m,
 	ti->ti_sum = cksum(m, tlen);
 
 	struct tcpiphdr tcpiph_save = *(mtod(m, struct tcpiphdr *));
+	struct ip *ip;
+
+	switch (af) {
+	case AF_INET:
 	m->m_data += sizeof(struct tcpiphdr) - sizeof(struct tcphdr)
 	                                     - sizeof(struct ip);
 	m->m_len  -= sizeof(struct tcpiphdr) - sizeof(struct tcphdr)
 	                                     - sizeof(struct ip);
-	struct ip *ip = mtod(m, struct ip *);
+	ip = mtod(m, struct ip *);
 	ip->ip_len = tlen;
 	ip->ip_dst = tcpiph_save.ti_dst;
 	ip->ip_src = tcpiph_save.ti_src;
@@ -185,6 +202,11 @@ tcp_respond(struct tcpcb *tp, struct tcpiphdr *ti, struct mbuf *m,
 	}
 
 	(void) ip_output((struct socket *)0, m);
+	    break;
+
+	default:
+	    g_assert_not_reached();
+	}
 }
 
 /*
@@ -388,8 +410,8 @@ void tcp_connect(struct socket *inso)
 {
     Slirp *slirp = inso->slirp;
     struct socket *so;
-    struct sockaddr_in addr;
-    socklen_t addrlen = sizeof(struct sockaddr_in);
+    struct sockaddr_storage addr;
+    socklen_t addrlen = sizeof(struct sockaddr_storage);
     struct tcpcb *tp;
     int s, opt;
 
@@ -414,9 +436,8 @@ void tcp_connect(struct socket *inso)
             free(so); /* NOT sofree */
             return;
         }
-        so->so_lfamily = AF_INET;
-        so->so_laddr = inso->so_laddr;
-        so->so_lport = inso->so_lport;
+        so->lhost = inso->lhost;
+        so->so_ffamily = inso->so_ffamily;
     }
 
     tcp_mss(sototcpcb(so), 0);
@@ -432,7 +453,7 @@ void tcp_connect(struct socket *inso)
     qemu_setsockopt(s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(int));
     socket_set_nodelay(s);
 
-    so->fhost.sin = addr;
+    so->fhost.ss = addr;
     sotranslate_accept(so);
 
     /* Close the accept() socket, set right state */
diff --git a/slirp/tcp_timer.c b/slirp/tcp_timer.c
index 1214c2e..8f5dd77 100644
--- a/slirp/tcp_timer.c
+++ b/slirp/tcp_timer.c
@@ -278,7 +278,8 @@ tcp_timers(register struct tcpcb *tp, int timer)
 			 * correspondent TCP to respond.
 			 */
 			tcp_respond(tp, &tp->t_template, (struct mbuf *)NULL,
-			    tp->rcv_nxt, tp->snd_una - 1, 0);
+			    tp->rcv_nxt, tp->snd_una - 1, 0,
+			    tp->t_socket->so_ffamily);
 			tp->t_timer[TCPT_KEEP] = TCPTV_KEEPINTVL;
 		} else
 			tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_IDLE;
-- 
2.7.0

^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [Qemu-devel] [PATCHv9 06/10] slirp: Reindent after refactoring
  2016-02-22 19:28 [Qemu-devel] [PATCHv9 0/10] slirp: Adding IPv6 support to Qemu -net user mode Samuel Thibault
                   ` (4 preceding siblings ...)
  2016-02-22 19:28 ` [Qemu-devel] [PATCHv9 05/10] slirp: Generalizing and neutralizing various TCP functions before adding IPv6 stuff Samuel Thibault
@ 2016-02-22 19:28 ` Samuel Thibault
  2016-03-07  7:02   ` Jason Wang
  2016-02-22 19:28 ` [Qemu-devel] [PATCHv9 07/10] slirp: Handle IPv6 in TCP functions Samuel Thibault
                   ` (5 subsequent siblings)
  11 siblings, 1 reply; 51+ messages in thread
From: Samuel Thibault @ 2016-02-22 19:28 UTC (permalink / raw)
  To: qemu-devel
  Cc: Thomas Huth, zhanghailiang, Li Zhijian, Stefan Hajnoczi,
	Jason Wang, Dave Gilbert, Vasiliy Tolstov, Huangpeng, Gonglei,
	Jan Kiszka, Samuel Thibault, Guillaume Subiron

From: Guillaume Subiron <maethor@subiron.org>

No code change.

Signed-off-by: Guillaume Subiron <maethor@subiron.org>
Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
Reviewed-by: Thomas Huth <thuth@redhat.com>
---
 slirp/tcp_input.c  | 92 +++++++++++++++++++++++++++---------------------------
 slirp/tcp_output.c | 29 +++++++++--------
 slirp/tcp_subr.c   | 50 ++++++++++++++---------------
 3 files changed, 85 insertions(+), 86 deletions(-)

diff --git a/slirp/tcp_input.c b/slirp/tcp_input.c
index a2f1044..6427c90 100644
--- a/slirp/tcp_input.c
+++ b/slirp/tcp_input.c
@@ -258,48 +258,48 @@ tcp_input(struct mbuf *m, int iphlen, struct socket *inso, unsigned short af)
 
 	switch (af) {
 	case AF_INET:
-	if (iphlen > sizeof(struct ip )) {
-	  ip_stripoptions(m, (struct mbuf *)0);
-	  iphlen=sizeof(struct ip );
-	}
-	/* XXX Check if too short */
+	    if (iphlen > sizeof(struct ip)) {
+	        ip_stripoptions(m, (struct mbuf *)0);
+	        iphlen = sizeof(struct ip);
+	    }
+	    /* XXX Check if too short */
 
 
-	/*
-	 * Save a copy of the IP header in case we want restore it
-	 * for sending an ICMP error message in response.
-	 */
-	ip=mtod(m, struct ip *);
-	save_ip = *ip;
-	save_ip.ip_len+= iphlen;
+	    /*
+	     * Save a copy of the IP header in case we want restore it
+	     * for sending an ICMP error message in response.
+	     */
+	    ip = mtod(m, struct ip *);
+	    save_ip = *ip;
+	    save_ip.ip_len += iphlen;
 
-	/*
-	 * Get IP and TCP header together in first mbuf.
-	 * Note: IP leaves IP header in first mbuf.
-	 */
-	m->m_data -= sizeof(struct tcpiphdr) - sizeof(struct ip)
-	                                     - sizeof(struct tcphdr);
-	m->m_len += sizeof(struct tcpiphdr) - sizeof(struct ip)
-	                                    - sizeof(struct tcphdr);
-	ti = mtod(m, struct tcpiphdr *);
+	    /*
+	     * Get IP and TCP header together in first mbuf.
+	     * Note: IP leaves IP header in first mbuf.
+	     */
+	    m->m_data -= sizeof(struct tcpiphdr) - sizeof(struct ip)
+	                                         - sizeof(struct tcphdr);
+	    m->m_len += sizeof(struct tcpiphdr) - sizeof(struct ip)
+	                                        - sizeof(struct tcphdr);
+	    ti = mtod(m, struct tcpiphdr *);
 
-	/*
-	 * Checksum extended TCP header and data.
-	 */
-	tlen = ip->ip_len;
-	tcpiphdr2qlink(ti)->next = tcpiphdr2qlink(ti)->prev = NULL;
-	memset(&ti->ih_mbuf, 0 , sizeof(struct mbuf_ptr));
-	memset(&ti->ti, 0, sizeof(ti->ti));
-	ti->ti_x0 = 0;
-	ti->ti_src = save_ip.ip_src;
-	ti->ti_dst = save_ip.ip_dst;
-	ti->ti_pr = save_ip.ip_p;
-	ti->ti_len = htons((uint16_t)tlen);
-	len = ((sizeof(struct tcpiphdr) - sizeof(struct tcphdr)) + tlen);
-	if(cksum(m, len)) {
-	  goto drop;
-	}
-	break;
+	    /*
+	     * Checksum extended TCP header and data.
+	     */
+	    tlen = ip->ip_len;
+	    tcpiphdr2qlink(ti)->next = tcpiphdr2qlink(ti)->prev = NULL;
+	    memset(&ti->ih_mbuf, 0 , sizeof(struct mbuf_ptr));
+	    memset(&ti->ti, 0, sizeof(ti->ti));
+	    ti->ti_x0 = 0;
+	    ti->ti_src = save_ip.ip_src;
+	    ti->ti_dst = save_ip.ip_dst;
+	    ti->ti_pr = save_ip.ip_p;
+	    ti->ti_len = htons((uint16_t)tlen);
+	    len = ((sizeof(struct tcpiphdr) - sizeof(struct tcphdr)) + tlen);
+	    if (cksum(m, len)) {
+	        goto drop;
+	    }
+	    break;
 
 	default:
 	    g_assert_not_reached();
@@ -343,12 +343,12 @@ findso:
 	fhost.ss_family = af;
 	switch (af) {
 	case AF_INET:
-	lhost4 = (struct sockaddr_in *) &lhost;
-	lhost4->sin_addr = ti->ti_src;
-	lhost4->sin_port = ti->ti_sport;
-	fhost4 = (struct sockaddr_in *) &fhost;
-	fhost4->sin_addr = ti->ti_dst;
-	fhost4->sin_port = ti->ti_dport;
+	    lhost4 = (struct sockaddr_in *) &lhost;
+	    lhost4->sin_addr = ti->ti_src;
+	    lhost4->sin_port = ti->ti_sport;
+	    fhost4 = (struct sockaddr_in *) &fhost;
+	    fhost4->sin_addr = ti->ti_dst;
+	    fhost4->sin_port = ti->ti_dport;
 	    break;
 	default:
 	    g_assert_not_reached();
@@ -591,8 +591,8 @@ findso:
 	   * tcp_ctl once connected, otherwise connect
 	   */
 	  if (af == AF_INET &&
-	      (so->so_faddr.s_addr & slirp->vnetwork_mask.s_addr) ==
-	      slirp->vnetwork_addr.s_addr) {
+	         (so->so_faddr.s_addr & slirp->vnetwork_mask.s_addr) ==
+	         slirp->vnetwork_addr.s_addr) {
 	    if (so->so_faddr.s_addr != slirp->vhost_addr.s_addr &&
 		so->so_faddr.s_addr != slirp->vnameserver_addr.s_addr) {
 		/* May be an add exec */
diff --git a/slirp/tcp_output.c b/slirp/tcp_output.c
index 32201fb..eec8902 100644
--- a/slirp/tcp_output.c
+++ b/slirp/tcp_output.c
@@ -452,21 +452,20 @@ send:
 
 	switch (so->so_ffamily) {
 	case AF_INET:
-	m->m_data += sizeof(struct tcpiphdr) - sizeof(struct tcphdr)
-	                                     - sizeof(struct ip);
-	m->m_len  -= sizeof(struct tcpiphdr) - sizeof(struct tcphdr)
-	                                     - sizeof(struct ip);
-	ip = mtod(m, struct ip *);
-
-	ip->ip_len = m->m_len;
-	ip->ip_dst = tcpiph_save.ti_dst;
-	ip->ip_src = tcpiph_save.ti_src;
-	ip->ip_p = tcpiph_save.ti_pr;
-
-	ip->ip_ttl = IPDEFTTL;
-	ip->ip_tos = so->so_iptos;
-
-	error = ip_output(so, m);
+	    m->m_data += sizeof(struct tcpiphdr) - sizeof(struct tcphdr)
+	                                         - sizeof(struct ip);
+	    m->m_len  -= sizeof(struct tcpiphdr) - sizeof(struct tcphdr)
+	                                         - sizeof(struct ip);
+	    ip = mtod(m, struct ip *);
+
+	    ip->ip_len = m->m_len;
+	    ip->ip_dst = tcpiph_save.ti_dst;
+	    ip->ip_src = tcpiph_save.ti_src;
+	    ip->ip_p = tcpiph_save.ti_pr;
+
+	    ip->ip_ttl = IPDEFTTL;
+	    ip->ip_tos = so->so_iptos;
+	    error = ip_output(so, m);
 	    break;
 
 	default:
diff --git a/slirp/tcp_subr.c b/slirp/tcp_subr.c
index ee101e2..c16b29d 100644
--- a/slirp/tcp_subr.c
+++ b/slirp/tcp_subr.c
@@ -80,12 +80,12 @@ tcp_template(struct tcpcb *tp)
 	n->ti_x0 = 0;
 	switch (so->so_ffamily) {
 	case AF_INET:
-	n->ti_pr = IPPROTO_TCP;
-	n->ti_len = htons(sizeof(struct tcphdr));
-	n->ti_src = so->so_faddr;
-	n->ti_dst = so->so_laddr;
-	n->ti_sport = so->so_fport;
-	n->ti_dport = so->so_lport;
+	    n->ti_pr = IPPROTO_TCP;
+	    n->ti_len = htons(sizeof(struct tcphdr));
+	    n->ti_src = so->so_faddr;
+	    n->ti_dst = so->so_laddr;
+	    n->ti_sport = so->so_fport;
+	    n->ti_dport = so->so_lport;
 	    break;
 
 	default:
@@ -153,8 +153,8 @@ tcp_respond(struct tcpcb *tp, struct tcpiphdr *ti, struct mbuf *m,
 #define xchg(a,b,type) { type t; t=a; a=b; b=t; }
 		switch (af) {
 		case AF_INET:
-		xchg(ti->ti_dst.s_addr, ti->ti_src.s_addr, uint32_t);
-		xchg(ti->ti_dport, ti->ti_sport, uint16_t);
+		    xchg(ti->ti_dst.s_addr, ti->ti_src.s_addr, uint32_t);
+		    xchg(ti->ti_dport, ti->ti_sport, uint16_t);
 		    break;
 		default:
 		    g_assert_not_reached();
@@ -185,23 +185,23 @@ tcp_respond(struct tcpcb *tp, struct tcpiphdr *ti, struct mbuf *m,
 
 	switch (af) {
 	case AF_INET:
-	m->m_data += sizeof(struct tcpiphdr) - sizeof(struct tcphdr)
-	                                     - sizeof(struct ip);
-	m->m_len  -= sizeof(struct tcpiphdr) - sizeof(struct tcphdr)
-	                                     - sizeof(struct ip);
-	ip = mtod(m, struct ip *);
-	ip->ip_len = tlen;
-	ip->ip_dst = tcpiph_save.ti_dst;
-	ip->ip_src = tcpiph_save.ti_src;
-	ip->ip_p = tcpiph_save.ti_pr;
-
-	if (flags & TH_RST) {
-		ip->ip_ttl = MAXTTL;
-	} else {
-		ip->ip_ttl = IPDEFTTL;
-	}
-
-	(void) ip_output((struct socket *)0, m);
+	    m->m_data += sizeof(struct tcpiphdr) - sizeof(struct tcphdr)
+	                                         - sizeof(struct ip);
+	    m->m_len  -= sizeof(struct tcpiphdr) - sizeof(struct tcphdr)
+	                                         - sizeof(struct ip);
+	    ip = mtod(m, struct ip *);
+	    ip->ip_len = tlen;
+	    ip->ip_dst = tcpiph_save.ti_dst;
+	    ip->ip_src = tcpiph_save.ti_src;
+	    ip->ip_p = tcpiph_save.ti_pr;
+
+	    if (flags & TH_RST) {
+	        ip->ip_ttl = MAXTTL;
+	    } else {
+	        ip->ip_ttl = IPDEFTTL;
+	    }
+
+	    (void) ip_output((struct socket *)0, m);
 	    break;
 
 	default:
-- 
2.7.0

^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [Qemu-devel] [PATCHv9 07/10] slirp: Handle IPv6 in TCP functions
  2016-02-22 19:28 [Qemu-devel] [PATCHv9 0/10] slirp: Adding IPv6 support to Qemu -net user mode Samuel Thibault
                   ` (5 preceding siblings ...)
  2016-02-22 19:28 ` [Qemu-devel] [PATCHv9 06/10] slirp: Reindent after refactoring Samuel Thibault
@ 2016-02-22 19:28 ` Samuel Thibault
  2016-02-22 19:28 ` [Qemu-devel] [PATCHv9 08/10] slirp: Adding IPv6 address for DNS relay Samuel Thibault
                   ` (4 subsequent siblings)
  11 siblings, 0 replies; 51+ messages in thread
From: Samuel Thibault @ 2016-02-22 19:28 UTC (permalink / raw)
  To: qemu-devel
  Cc: Thomas Huth, zhanghailiang, Li Zhijian, Stefan Hajnoczi,
	Jason Wang, Dave Gilbert, Vasiliy Tolstov, Huangpeng, Gonglei,
	Jan Kiszka, Samuel Thibault, Guillaume Subiron

From: Guillaume Subiron <maethor@subiron.org>

This patch adds IPv6 case in TCP functions refactored by the last
patches.
This also adds IPv6 pseudo-header in tcpiphdr structure.
Finally, tcp_input() is called by ip6_input().

Signed-off-by: Guillaume Subiron <maethor@subiron.org>
Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
Reviewed-by: Thomas Huth <thuth@redhat.com>
---
 slirp/ip6_input.c  |  3 ++-
 slirp/tcp.h        |  2 ++
 slirp/tcp_input.c  | 58 +++++++++++++++++++++++++++++++++++++++++++-----------
 slirp/tcp_output.c | 16 +++++++++++++++
 slirp/tcp_subr.c   | 32 ++++++++++++++++++++++++++++--
 slirp/tcpip.h      |  9 +++++++++
 6 files changed, 106 insertions(+), 14 deletions(-)

diff --git a/slirp/ip6_input.c b/slirp/ip6_input.c
index 9ca6d32..c0b11e7 100644
--- a/slirp/ip6_input.c
+++ b/slirp/ip6_input.c
@@ -55,7 +55,8 @@ void ip6_input(struct mbuf *m)
      */
     switch (ip6->ip_nh) {
     case IPPROTO_TCP:
-        icmp6_send_error(m, ICMP6_UNREACH, ICMP6_UNREACH_NO_ROUTE);
+        NTOHS(ip6->ip_pl);
+        tcp_input(m, sizeof(struct ip6), (struct socket *)NULL, AF_INET6);
         break;
     case IPPROTO_UDP:
         udp6_input(m);
diff --git a/slirp/tcp.h b/slirp/tcp.h
index 2e2b403..61befcd 100644
--- a/slirp/tcp.h
+++ b/slirp/tcp.h
@@ -106,6 +106,8 @@ struct tcphdr {
  */
 #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/slirp/tcp_input.c b/slirp/tcp_input.c
index 6427c90..76f719d 100644
--- a/slirp/tcp_input.c
+++ b/slirp/tcp_input.c
@@ -216,7 +216,8 @@ present:
 void
 tcp_input(struct mbuf *m, int iphlen, struct socket *inso, unsigned short af)
 {
-  	struct ip save_ip, *ip;
+	struct ip save_ip, *ip;
+	struct ip6 save_ip6, *ip6;
 	register struct tcpiphdr *ti;
 	caddr_t optp = NULL;
 	int optlen = 0;
@@ -230,6 +231,7 @@ tcp_input(struct mbuf *m, int iphlen, struct socket *inso, unsigned short af)
 	int ret;
 	struct sockaddr_storage lhost, fhost;
 	struct sockaddr_in *lhost4, *fhost4;
+	struct sockaddr_in6 *lhost6, *fhost6;
     struct ex_list *ex_ptr;
     Slirp *slirp;
 
@@ -256,6 +258,9 @@ tcp_input(struct mbuf *m, int iphlen, struct socket *inso, unsigned short af)
 	}
 	slirp = m->slirp;
 
+	ip = mtod(m, struct ip *);
+	ip6 = mtod(m, struct ip6 *);
+
 	switch (af) {
 	case AF_INET:
 	    if (iphlen > sizeof(struct ip)) {
@@ -264,12 +269,6 @@ tcp_input(struct mbuf *m, int iphlen, struct socket *inso, unsigned short af)
 	    }
 	    /* XXX Check if too short */
 
-
-	    /*
-	     * Save a copy of the IP header in case we want restore it
-	     * for sending an ICMP error message in response.
-	     */
-	    ip = mtod(m, struct ip *);
 	    save_ip = *ip;
 	    save_ip.ip_len += iphlen;
 
@@ -295,16 +294,36 @@ tcp_input(struct mbuf *m, int iphlen, struct socket *inso, unsigned short af)
 	    ti->ti_dst = save_ip.ip_dst;
 	    ti->ti_pr = save_ip.ip_p;
 	    ti->ti_len = htons((uint16_t)tlen);
-	    len = ((sizeof(struct tcpiphdr) - sizeof(struct tcphdr)) + tlen);
-	    if (cksum(m, len)) {
-	        goto drop;
-	    }
+	    break;
+
+	case AF_INET6:
+	    save_ip6 = *ip6;
+	    m->m_data -= sizeof(struct tcpiphdr) - (sizeof(struct ip6)
+	                                         + sizeof(struct tcphdr));
+	    m->m_len  += sizeof(struct tcpiphdr) - (sizeof(struct ip6)
+	                                         + sizeof(struct tcphdr));
+	    ti = mtod(m, struct tcpiphdr *);
+
+	    tlen = ip6->ip_pl;
+	    tcpiphdr2qlink(ti)->next = tcpiphdr2qlink(ti)->prev = NULL;
+	    memset(&ti->ih_mbuf, 0 , sizeof(struct mbuf_ptr));
+	    memset(&ti->ti, 0, sizeof(ti->ti));
+	    ti->ti_x0 = 0;
+	    ti->ti_src6 = save_ip6.ip_src;
+	    ti->ti_dst6 = save_ip6.ip_dst;
+	    ti->ti_nh6 = save_ip6.ip_nh;
+	    ti->ti_len = htons((uint16_t)tlen);
 	    break;
 
 	default:
 	    g_assert_not_reached();
 	}
 
+	len = ((sizeof(struct tcpiphdr) - sizeof(struct tcphdr)) + tlen);
+	if (cksum(m, len)) {
+	    goto drop;
+	}
+
 	/*
 	 * Check that TCP offset makes sense,
 	 * pull out TCP options and adjust length.		XXX
@@ -350,6 +369,14 @@ findso:
 	    fhost4->sin_addr = ti->ti_dst;
 	    fhost4->sin_port = ti->ti_dport;
 	    break;
+	case AF_INET6:
+	    lhost6 = (struct sockaddr_in6 *) &lhost;
+	    lhost6->sin6_addr = ti->ti_src6;
+	    lhost6->sin6_port = ti->ti_sport;
+	    fhost6 = (struct sockaddr_in6 *) &fhost;
+	    fhost6->sin6_addr = ti->ti_dst6;
+	    fhost6->sin6_port = ti->ti_dport;
+	    break;
 	default:
 	    g_assert_not_reached();
 	}
@@ -408,6 +435,8 @@ findso:
 	      case AF_INET:
 	          so->so_iptos = ((struct ip *)ti)->ip_tos;
 	          break;
+	      case AF_INET6:
+	          break;
 	      default:
 	          g_assert_not_reached();
 	      }
@@ -642,6 +671,9 @@ findso:
 	      case AF_INET:
 	          *ip = save_ip;
 	          break;
+	      case AF_INET6:
+	          *ip6 = save_ip6;
+	          break;
 	      default:
 	          g_assert_not_reached();
 	      }
@@ -1517,6 +1549,10 @@ tcp_mss(struct tcpcb *tp, u_int offer)
 	    mss = min(IF_MTU, IF_MRU) - sizeof(struct tcphdr)
 	                              + sizeof(struct ip);
 	    break;
+	case AF_INET6:
+	    mss = min(IF_MTU, IF_MRU) - sizeof(struct tcphdr)
+	                              + sizeof(struct ip6);
+	    break;
 	default:
 	    g_assert_not_reached();
 	}
diff --git a/slirp/tcp_output.c b/slirp/tcp_output.c
index eec8902..99b0a9b 100644
--- a/slirp/tcp_output.c
+++ b/slirp/tcp_output.c
@@ -63,6 +63,7 @@ tcp_output(struct tcpcb *tp)
 	register struct mbuf *m;
 	register struct tcpiphdr *ti, tcpiph_save;
 	struct ip *ip;
+	struct ip6 *ip6;
 	u_char opt[MAX_TCPOPTLEN];
 	unsigned optlen, hdrlen;
 	int idle, sendalot;
@@ -468,6 +469,21 @@ send:
 	    error = ip_output(so, m);
 	    break;
 
+	case AF_INET6:
+	    m->m_data += sizeof(struct tcpiphdr) - sizeof(struct tcphdr)
+	                                         - sizeof(struct ip6);
+	    m->m_len  -= sizeof(struct tcpiphdr) - sizeof(struct tcphdr)
+	                                         - sizeof(struct ip6);
+	    ip6 = mtod(m, struct ip6 *);
+
+	    ip6->ip_pl = tcpiph_save.ti_len;
+	    ip6->ip_dst = tcpiph_save.ti_dst6;
+	    ip6->ip_src = tcpiph_save.ti_src6;
+	    ip6->ip_nh = tcpiph_save.ti_nh6;
+
+	    error = ip6_output(so, m, 0);
+	    break;
+
 	default:
 	    g_assert_not_reached();
 	}
diff --git a/slirp/tcp_subr.c b/slirp/tcp_subr.c
index c16b29d..dbfd2c6 100644
--- a/slirp/tcp_subr.c
+++ b/slirp/tcp_subr.c
@@ -88,6 +88,15 @@ tcp_template(struct tcpcb *tp)
 	    n->ti_dport = so->so_lport;
 	    break;
 
+	case AF_INET6:
+	    n->ti_nh6 = IPPROTO_TCP;
+	    n->ti_len = htons(sizeof(struct tcphdr));
+	    n->ti_src6 = so->so_faddr6;
+	    n->ti_dst6 = so->so_laddr6;
+	    n->ti_sport = so->so_fport6;
+	    n->ti_dport = so->so_lport6;
+	    break;
+
 	default:
 	    g_assert_not_reached();
 	}
@@ -156,6 +165,10 @@ tcp_respond(struct tcpcb *tp, struct tcpiphdr *ti, struct mbuf *m,
 		    xchg(ti->ti_dst.s_addr, ti->ti_src.s_addr, uint32_t);
 		    xchg(ti->ti_dport, ti->ti_sport, uint16_t);
 		    break;
+		case AF_INET6:
+		    xchg(ti->ti_dst6, ti->ti_src6, struct in6_addr);
+		    xchg(ti->ti_dport, ti->ti_sport, uint16_t);
+		    break;
 		default:
 		    g_assert_not_reached();
 		}
@@ -182,6 +195,7 @@ tcp_respond(struct tcpcb *tp, struct tcpiphdr *ti, struct mbuf *m,
 
 	struct tcpiphdr tcpiph_save = *(mtod(m, struct tcpiphdr *));
 	struct ip *ip;
+	struct ip6 *ip6;
 
 	switch (af) {
 	case AF_INET:
@@ -201,7 +215,21 @@ tcp_respond(struct tcpcb *tp, struct tcpiphdr *ti, struct mbuf *m,
 	        ip->ip_ttl = IPDEFTTL;
 	    }
 
-	    (void) ip_output((struct socket *)0, m);
+	    ip_output(NULL, m);
+	    break;
+
+	case AF_INET6:
+	    m->m_data += sizeof(struct tcpiphdr) - sizeof(struct tcphdr)
+	                                         - sizeof(struct ip6);
+	    m->m_len  -= sizeof(struct tcpiphdr) - sizeof(struct tcphdr)
+	                                         - sizeof(struct ip6);
+	    ip6 = mtod(m, struct ip6 *);
+	    ip6->ip_pl = tlen;
+	    ip6->ip_dst = tcpiph_save.ti_dst6;
+	    ip6->ip_src = tcpiph_save.ti_src6;
+	    ip6->ip_nh = tcpiph_save.ti_nh6;
+
+	    ip6_output(NULL, m, 0);
 	    break;
 
 	default:
@@ -225,7 +253,7 @@ tcp_newtcpcb(struct socket *so)
 
 	memset((char *) tp, 0, sizeof(struct tcpcb));
 	tp->seg_next = tp->seg_prev = (struct tcpiphdr*)tp;
-	tp->t_maxseg = TCP_MSS;
+	tp->t_maxseg = (so->so_ffamily == AF_INET) ? TCP_MSS : TCP6_MSS;
 
 	tp->t_flags = TCP_DO_RFC1323 ? (TF_REQ_SCALE|TF_REQ_TSTMP) : 0;
 	tp->t_socket = so;
diff --git a/slirp/tcpip.h b/slirp/tcpip.h
index 3c5d127..124b4a9 100644
--- a/slirp/tcpip.h
+++ b/slirp/tcpip.h
@@ -45,6 +45,12 @@ struct tcpiphdr {
             uint8_t ih_x1;          /* (unused) */
             uint8_t ih_pr;          /* protocol */
         } ti_i4;
+        struct {
+            struct  in6_addr ih_src;
+            struct  in6_addr ih_dst;
+            uint8_t ih_x1;
+            uint8_t ih_nh;
+        } ti_i6;
     } ti;
     uint16_t    ti_x0;
     uint16_t    ti_len;             /* protocol length */
@@ -54,6 +60,9 @@ struct tcpiphdr {
 #define	ti_pr		ti.ti_i4.ih_pr
 #define	ti_src		ti.ti_i4.ih_src
 #define	ti_dst		ti.ti_i4.ih_dst
+#define	ti_src6		ti.ti_i6.ih_src
+#define	ti_dst6		ti.ti_i6.ih_dst
+#define	ti_nh6		ti.ti_i6.ih_nh
 #define	ti_sport	ti_t.th_sport
 #define	ti_dport	ti_t.th_dport
 #define	ti_seq		ti_t.th_seq
-- 
2.7.0

^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [Qemu-devel] [PATCHv9 08/10] slirp: Adding IPv6 address for DNS relay
  2016-02-22 19:28 [Qemu-devel] [PATCHv9 0/10] slirp: Adding IPv6 support to Qemu -net user mode Samuel Thibault
                   ` (6 preceding siblings ...)
  2016-02-22 19:28 ` [Qemu-devel] [PATCHv9 07/10] slirp: Handle IPv6 in TCP functions Samuel Thibault
@ 2016-02-22 19:28 ` Samuel Thibault
  2016-02-23  8:12   ` Thomas Huth
  2016-02-22 19:28 ` [Qemu-devel] [PATCHv9 09/10] qapi-schema, qemu-options & slirp: Adding Qemu options for IPv6 addresses Samuel Thibault
                   ` (3 subsequent siblings)
  11 siblings, 1 reply; 51+ messages in thread
From: Samuel Thibault @ 2016-02-22 19:28 UTC (permalink / raw)
  To: qemu-devel
  Cc: Thomas Huth, zhanghailiang, Li Zhijian, Stefan Hajnoczi,
	Jason Wang, Dave Gilbert, Vasiliy Tolstov, Huangpeng, Gonglei,
	Jan Kiszka, Samuel Thibault, Guillaume Subiron

From: Guillaume Subiron <maethor@subiron.org>

This patch adds an IPv6 address to the DNS relay. in6_equal_dns() is
developed using this Slirp attribute.
sotranslate_in/out/accept() are also updated to manage the IPv6 case so the
guest can be able to join the host using one of the Slirp addresses.

For now this only points to localhost. Further development will be needed to
automatically fetch the IPv6 address from resolv.conf, and announce this via
RDNSS.

Signed-off-by: Guillaume Subiron <maethor@subiron.org>
Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
---
 slirp/ip6.h    |  6 +++++-
 slirp/slirp.c  |  1 +
 slirp/slirp.h  |  1 +
 slirp/socket.c | 32 ++++++++++++++++++++++++++++++++
 4 files changed, 39 insertions(+), 1 deletion(-)

diff --git a/slirp/ip6.h b/slirp/ip6.h
index 55e52a1..c2df8d3 100644
--- a/slirp/ip6.h
+++ b/slirp/ip6.h
@@ -73,7 +73,11 @@ static inline bool in6_equal_mach(const struct in6_addr *a,
   || (in6_equal_net(a, &(struct in6_addr)LINKLOCAL_ADDR, 64)\
       && in6_equal_mach(a, &slirp->vhost_addr6, 64)))
 
-#define in6_equal_dns(a) 0
+#define in6_equal_dns(a)\
+    ((in6_equal_net(a, &slirp->vprefix_addr6, slirp->vprefix_len)\
+      && in6_equal_mach(a, &slirp->vnameserver_addr6, slirp->vprefix_len))\
+  || (in6_equal_net(a, &(struct in6_addr)LINKLOCAL_ADDR, 64)\
+      && in6_equal_mach(a, &slirp->vnameserver_addr6, 64)))
 
 #define in6_equal_host(a)\
     (in6_equal_router(a) || in6_equal_dns(a))
diff --git a/slirp/slirp.c b/slirp/slirp.c
index d908422..a201a5a 100644
--- a/slirp/slirp.c
+++ b/slirp/slirp.c
@@ -234,6 +234,7 @@ Slirp *slirp_init(int restricted, struct in_addr vnetwork,
     slirp->bootp_filename = g_strdup(bootfile);
     slirp->vdhcp_startaddr = vdhcp_start;
     slirp->vnameserver_addr = vnameserver;
+    inet_pton(AF_INET6, "fec0::3", &slirp->vnameserver_addr6);
 
     if (vdnssearch) {
         translate_dnssearch(slirp, vdnssearch);
diff --git a/slirp/slirp.h b/slirp/slirp.h
index 967d93e..a830353 100644
--- a/slirp/slirp.h
+++ b/slirp/slirp.h
@@ -232,6 +232,7 @@ struct Slirp {
     struct in6_addr vhost_addr6;
     struct in_addr vdhcp_startaddr;
     struct in_addr vnameserver_addr;
+    struct in6_addr vnameserver_addr6;
 
     struct in_addr client_ipaddr;
     char client_hostname[33];
diff --git a/slirp/socket.c b/slirp/socket.c
index d4b02c8..0661fa9 100644
--- a/slirp/socket.c
+++ b/slirp/socket.c
@@ -747,6 +747,7 @@ void sotranslate_out(struct socket *so, struct sockaddr_storage *addr)
 {
     Slirp *slirp = so->slirp;
     struct sockaddr_in *sin = (struct sockaddr_in *)addr;
+    struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)addr;
 
     switch (addr->ss_family) {
     case AF_INET:
@@ -767,6 +768,19 @@ void sotranslate_out(struct socket *so, struct sockaddr_storage *addr)
             ntohs(sin->sin_port), inet_ntoa(sin->sin_addr)));
         break;
 
+    case AF_INET6:
+        if (in6_equal_net(&so->so_faddr6, &slirp->vprefix_addr6,
+                    slirp->vprefix_len)) {
+            if (in6_equal(&so->so_faddr6, &slirp->vnameserver_addr6)) {
+                /*if (get_dns_addr(&addr) < 0) {*/ /* TODO */
+                    sin6->sin6_addr = in6addr_loopback;
+                /*}*/
+            } else {
+                sin6->sin6_addr = in6addr_loopback;
+            }
+        }
+        break;
+
     default:
         break;
     }
@@ -776,6 +790,7 @@ void sotranslate_in(struct socket *so, struct sockaddr_storage *addr)
 {
     Slirp *slirp = so->slirp;
     struct sockaddr_in *sin = (struct sockaddr_in *)addr;
+    struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)addr;
 
     switch (addr->ss_family) {
     case AF_INET:
@@ -792,6 +807,16 @@ void sotranslate_in(struct socket *so, struct sockaddr_storage *addr)
         }
         break;
 
+    case AF_INET6:
+        if (in6_equal_net(&so->so_faddr6, &slirp->vprefix_addr6,
+                    slirp->vprefix_len)) {
+            if (in6_equal(&sin6->sin6_addr, &in6addr_loopback)
+                    || !in6_equal(&so->so_faddr6, &slirp->vhost_addr6)) {
+                sin6->sin6_addr = so->so_faddr6;
+            }
+        }
+        break;
+
     default:
         break;
     }
@@ -813,6 +838,13 @@ void sotranslate_accept(struct socket *so)
         }
         break;
 
+   case AF_INET6:
+        if (in6_equal(&so->so_faddr6, &in6addr_any) ||
+                in6_equal(&so->so_faddr6, &in6addr_loopback)) {
+           so->so_faddr6 = slirp->vhost_addr6;
+        }
+        break;
+
     default:
         break;
     }
-- 
2.7.0

^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [Qemu-devel] [PATCHv9 09/10] qapi-schema, qemu-options & slirp: Adding Qemu options for IPv6 addresses
  2016-02-22 19:28 [Qemu-devel] [PATCHv9 0/10] slirp: Adding IPv6 support to Qemu -net user mode Samuel Thibault
                   ` (7 preceding siblings ...)
  2016-02-22 19:28 ` [Qemu-devel] [PATCHv9 08/10] slirp: Adding IPv6 address for DNS relay Samuel Thibault
@ 2016-02-22 19:28 ` Samuel Thibault
  2016-02-23  8:27   ` Thomas Huth
  2016-03-07  7:05   ` Jason Wang
  2016-02-22 19:28 ` [Qemu-devel] [PATCHv9 10/10] slirp: Add IPv6 support to the TFTP code Samuel Thibault
                   ` (2 subsequent siblings)
  11 siblings, 2 replies; 51+ messages in thread
From: Samuel Thibault @ 2016-02-22 19:28 UTC (permalink / raw)
  To: qemu-devel
  Cc: Thomas Huth, zhanghailiang, Li Zhijian, Stefan Hajnoczi,
	Jason Wang, Dave Gilbert, Vasiliy Tolstov, Huangpeng,
	Yann Bordenave, Gonglei, Jan Kiszka, Samuel Thibault,
	Guillaume Subiron

From: Yann Bordenave <meow@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 <meow@meowstars.org>
Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
---
 net/net.c        | 31 +++++++++++++++++++++++++
 net/slirp.c      | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++-----
 qapi-schema.json | 40 ++++++++++++++++++++------------
 qemu-options.hx  | 18 +++++++++++++--
 slirp/libslirp.h |  8 ++++---
 slirp/slirp.c    | 16 +++++++------
 6 files changed, 150 insertions(+), 32 deletions(-)

diff --git a/net/net.c b/net/net.c
index aebf753..d67904f 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..bd712bc 100644
--- a/net/slirp.c
+++ b/net/slirp.c
@@ -36,6 +36,7 @@
 #include "qemu/error-report.h"
 #include "qemu/sockets.h"
 #include "slirp/libslirp.h"
+#include "slirp/ip6.h"
 #include "sysemu/char.h"
 
 static int get_str_sep(char *buf, int buf_size, const char **pp, int sep)
@@ -135,10 +136,13 @@ 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 */
@@ -146,6 +150,9 @@ 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 in6_addr ip6_prefix;
+    struct in6_addr ip6_host;
+    struct in6_addr ip6_dns;
 #ifndef _WIN32
     struct in_addr smbsrv = { .s_addr = 0 };
 #endif
@@ -235,6 +242,52 @@ static int net_slirp_init(NetClientState *peer, const char *model,
     }
 #endif
 
+
+    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) {
+        if (!inet_pton(AF_INET6, vhost6, &ip6_host)) {
+            return -1;
+        }
+        if (!in6_equal_net(&ip6_prefix, &ip6_host, vprefix6_len)) {
+            return -1;
+        }
+    } else {
+        if (vprefix6_len > 126) {
+            return -1;
+        }
+        ip6_host = ip6_prefix;
+        ip6_host.s6_addr[15] |= 2;
+    }
+
+    if (vnameserver6) {
+        if (!inet_pton(AF_INET6, vnameserver6, &ip6_dns)) {
+            return -1;
+        }
+        if (!in6_equal_net(&ip6_prefix, &ip6_dns, vprefix6_len)) {
+            return -1;
+        }
+    } else {
+        if (vprefix6_len > 126) {
+            return -1;
+        }
+        ip6_dns = ip6_prefix;
+        ip6_dns.s6_addr[15] |= 3;
+    }
+
+
     nc = qemu_new_net_client(&net_slirp_info, peer, model, name);
 
     snprintf(nc->info_str, sizeof(nc->info_str),
@@ -243,8 +296,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 +816,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 2f0465e..a2c1214 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -1546,8 +1546,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"
@@ -1704,6 +1705,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.
+
 @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
@@ -1721,6 +1730,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.
+
 @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
diff --git a/slirp/libslirp.h b/slirp/libslirp.h
index 5bdcbd5..c4b25c9 100644
--- a/slirp/libslirp.h
+++ b/slirp/libslirp.h
@@ -10,9 +10,11 @@ int get_dns_addr(struct in_addr *pdns_addr);
 
 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 vnameserver, const char **vdnssearch,
+                  struct in6_addr vprefix_addr6, uint8_t vprefix_len,
+                  struct in6_addr vhost6, const char *vhostname,
+                  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);
 void slirp_cleanup(Slirp *slirp);
 
diff --git a/slirp/slirp.c b/slirp/slirp.c
index a201a5a..9ccf415 100644
--- a/slirp/slirp.c
+++ b/slirp/slirp.c
@@ -201,9 +201,11 @@ static int slirp_state_load(QEMUFile *f, void *opaque, int version_id);
 
 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 vnameserver, const char **vdnssearch,
+                  struct in6_addr vprefix_addr6, uint8_t vprefix_len,
+                  struct in6_addr vhost6, const char *vhostname,
+                  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)
 {
     Slirp *slirp = g_malloc0(sizeof(Slirp));
@@ -223,9 +225,9 @@ Slirp *slirp_init(int restricted, struct in_addr vnetwork,
     slirp->vnetwork_addr = vnetwork;
     slirp->vnetwork_mask = vnetmask;
     slirp->vhost_addr = vhost;
-    inet_pton(AF_INET6, "fec0::0", &slirp->vprefix_addr6);
-    slirp->vprefix_len = 64;
-    inet_pton(AF_INET6, "fec0::2", &slirp->vhost_addr6);
+    slirp->vprefix_addr6 = vprefix_addr6;
+    slirp->vprefix_len = vprefix_len;
+    slirp->vhost_addr6 = vhost6;
     if (vhostname) {
         pstrcpy(slirp->client_hostname, sizeof(slirp->client_hostname),
                 vhostname);
@@ -234,7 +236,7 @@ Slirp *slirp_init(int restricted, struct in_addr vnetwork,
     slirp->bootp_filename = g_strdup(bootfile);
     slirp->vdhcp_startaddr = vdhcp_start;
     slirp->vnameserver_addr = vnameserver;
-    inet_pton(AF_INET6, "fec0::3", &slirp->vnameserver_addr6);
+    slirp->vnameserver_addr6 = vnameserver6;
 
     if (vdnssearch) {
         translate_dnssearch(slirp, vdnssearch);
-- 
2.7.0

^ permalink raw reply related	[flat|nested] 51+ messages in thread

* [Qemu-devel] [PATCHv9 10/10] slirp: Add IPv6 support to the TFTP code
  2016-02-22 19:28 [Qemu-devel] [PATCHv9 0/10] slirp: Adding IPv6 support to Qemu -net user mode Samuel Thibault
                   ` (8 preceding siblings ...)
  2016-02-22 19:28 ` [Qemu-devel] [PATCHv9 09/10] qapi-schema, qemu-options & slirp: Adding Qemu options for IPv6 addresses Samuel Thibault
@ 2016-02-22 19:28 ` Samuel Thibault
  2016-03-04  8:41 ` [Qemu-devel] [PATCHv9 0/10] slirp: Adding IPv6 support to Qemu -net user mode Thomas Huth
  2016-03-07  6:48 ` Jason Wang
  11 siblings, 0 replies; 51+ messages in thread
From: Samuel Thibault @ 2016-02-22 19:28 UTC (permalink / raw)
  To: qemu-devel
  Cc: Thomas Huth, zhanghailiang, Li Zhijian, Stefan Hajnoczi,
	Jason Wang, Dave Gilbert, Vasiliy Tolstov, Huangpeng, Gonglei,
	Jan Kiszka, Guillaume Subiron

From: Thomas Huth <thuth@redhat.com>

Add the handler code for incoming TFTP packets to udp6_input(),
and make sure that the TFTP code can send packets with both,
udp_output() and udp6_output() by introducing a wrapper function
called tftp_udp_output().

Signed-off-by: Thomas Huth <thuth@redhat.com>
Reviewed-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
---
 slirp/tftp.c | 133 +++++++++++++++++++++++++++++++++--------------------------
 slirp/tftp.h |   7 ++--
 slirp/udp.c  |  16 ++++---
 slirp/udp6.c |  16 +++++--
 4 files changed, 100 insertions(+), 72 deletions(-)

diff --git a/slirp/tftp.c b/slirp/tftp.c
index abb0106..25ad6ef 100644
--- a/slirp/tftp.c
+++ b/slirp/tftp.c
@@ -46,7 +46,8 @@ static void tftp_session_terminate(struct tftp_session *spt)
     spt->slirp = NULL;
 }
 
-static int tftp_session_allocate(Slirp *slirp, struct tftp_t *tp)
+static int tftp_session_allocate(Slirp *slirp, struct sockaddr_storage *srcsas,
+                                 struct tftp_t *tp)
 {
   struct tftp_session *spt;
   int k;
@@ -68,7 +69,7 @@ static int tftp_session_allocate(Slirp *slirp, struct tftp_t *tp)
 
  found:
   memset(spt, 0, sizeof(*spt));
-  memcpy(&spt->client_ip, &tp->ip.ip_src, sizeof(spt->client_ip));
+  spt->client_addr = *srcsas;
   spt->fd = -1;
   spt->client_port = tp->udp.uh_sport;
   spt->slirp = slirp;
@@ -78,7 +79,8 @@ static int tftp_session_allocate(Slirp *slirp, struct tftp_t *tp)
   return k;
 }
 
-static int tftp_session_find(Slirp *slirp, struct tftp_t *tp)
+static int tftp_session_find(Slirp *slirp, struct sockaddr_storage *srcsas,
+                             struct tftp_t *tp)
 {
   struct tftp_session *spt;
   int k;
@@ -87,7 +89,7 @@ static int tftp_session_find(Slirp *slirp, struct tftp_t *tp)
     spt = &slirp->tftp_sessions[k];
 
     if (tftp_session_in_use(spt)) {
-      if (!memcmp(&spt->client_ip, &tp->ip.ip_src, sizeof(spt->client_ip))) {
+      if (sockaddr_equal(&spt->client_addr, srcsas)) {
 	if (spt->client_port == tp->udp.uh_sport) {
 	  return k;
 	}
@@ -120,11 +122,53 @@ static int tftp_read_data(struct tftp_session *spt, uint32_t block_nr,
     return bytes_read;
 }
 
+static struct tftp_t *tftp_prep_mbuf_data(struct tftp_session *spt,
+                                          struct mbuf *m)
+{
+    struct tftp_t *tp;
+
+    memset(m->m_data, 0, m->m_size);
+
+    m->m_data += IF_MAXLINKHDR;
+    if (spt->client_addr.ss_family == AF_INET6) {
+        m->m_data += sizeof(struct ip6);
+    } else {
+        m->m_data += sizeof(struct ip);
+    }
+    tp = (void *)m->m_data;
+    m->m_data += sizeof(struct udphdr);
+
+    return tp;
+}
+
+static void tftp_udp_output(struct tftp_session *spt, struct mbuf *m,
+                            struct tftp_t *recv_tp)
+{
+    if (spt->client_addr.ss_family == AF_INET6) {
+        struct sockaddr_in6 sa6, da6;
+
+        sa6.sin6_addr = spt->slirp->vhost_addr6;
+        sa6.sin6_port = recv_tp->udp.uh_dport;
+        da6.sin6_addr = ((struct sockaddr_in6 *)&spt->client_addr)->sin6_addr;
+        da6.sin6_port = spt->client_port;
+
+        udp6_output(NULL, m, &sa6, &da6);
+    } else {
+        struct sockaddr_in sa4, da4;
+
+        sa4.sin_addr = spt->slirp->vhost_addr;
+        sa4.sin_port = recv_tp->udp.uh_dport;
+        da4.sin_addr = ((struct sockaddr_in *)&spt->client_addr)->sin_addr;
+        da4.sin_port = spt->client_port;
+
+        udp_output(NULL, m, &sa4, &da4, IPTOS_LOWDELAY);
+    }
+}
+
 static int tftp_send_oack(struct tftp_session *spt,
                           const char *keys[], uint32_t values[], int nb,
                           struct tftp_t *recv_tp)
 {
-    struct sockaddr_in saddr, daddr;
     struct mbuf *m;
     struct tftp_t *tp;
     int i, n = 0;
@@ -132,13 +176,9 @@ static int tftp_send_oack(struct tftp_session *spt,
     m = m_get(spt->slirp);
 
     if (!m)
-	return -1;
-
-    memset(m->m_data, 0, m->m_size);
+        return -1;
 
-    m->m_data += IF_MAXLINKHDR;
-    tp = (void *)m->m_data;
-    m->m_data += sizeof(struct udpiphdr);
+    tp = tftp_prep_mbuf_data(spt, m);
 
     tp->tp_op = htons(TFTP_OACK);
     for (i = 0; i < nb; i++) {
@@ -148,15 +188,8 @@ static int tftp_send_oack(struct tftp_session *spt,
                       values[i]) + 1;
     }
 
-    saddr.sin_addr = recv_tp->ip.ip_dst;
-    saddr.sin_port = recv_tp->udp.uh_dport;
-
-    daddr.sin_addr = spt->client_ip;
-    daddr.sin_port = spt->client_port;
-
-    m->m_len = sizeof(struct tftp_t) - 514 + n -
-        sizeof(struct ip) - sizeof(struct udphdr);
-    udp_output(NULL, m, &saddr, &daddr, IPTOS_LOWDELAY);
+    m->m_len = sizeof(struct tftp_t) - 514 + n - sizeof(struct udphdr);
+    tftp_udp_output(spt, m, recv_tp);
 
     return 0;
 }
@@ -165,7 +198,6 @@ static void tftp_send_error(struct tftp_session *spt,
                             uint16_t errorcode, const char *msg,
                             struct tftp_t *recv_tp)
 {
-  struct sockaddr_in saddr, daddr;
   struct mbuf *m;
   struct tftp_t *tp;
 
@@ -177,24 +209,15 @@ static void tftp_send_error(struct tftp_session *spt,
 
   memset(m->m_data, 0, m->m_size);
 
-  m->m_data += IF_MAXLINKHDR;
-  tp = (void *)m->m_data;
-  m->m_data += sizeof(struct udpiphdr);
+  tp = tftp_prep_mbuf_data(spt, m);
 
   tp->tp_op = htons(TFTP_ERROR);
   tp->x.tp_error.tp_error_code = htons(errorcode);
   pstrcpy((char *)tp->x.tp_error.tp_msg, sizeof(tp->x.tp_error.tp_msg), msg);
 
-  saddr.sin_addr = recv_tp->ip.ip_dst;
-  saddr.sin_port = recv_tp->udp.uh_dport;
-
-  daddr.sin_addr = spt->client_ip;
-  daddr.sin_port = spt->client_port;
-
-  m->m_len = sizeof(struct tftp_t) - 514 + 3 + strlen(msg) -
-        sizeof(struct ip) - sizeof(struct udphdr);
-
-  udp_output(NULL, m, &saddr, &daddr, IPTOS_LOWDELAY);
+  m->m_len = sizeof(struct tftp_t) - 514 + 3 + strlen(msg)
+             - sizeof(struct udphdr);
+  tftp_udp_output(spt, m, recv_tp);
 
 out:
   tftp_session_terminate(spt);
@@ -203,7 +226,6 @@ out:
 static void tftp_send_next_block(struct tftp_session *spt,
                                  struct tftp_t *recv_tp)
 {
-  struct sockaddr_in saddr, daddr;
   struct mbuf *m;
   struct tftp_t *tp;
   int nobytes;
@@ -216,19 +238,11 @@ static void tftp_send_next_block(struct tftp_session *spt,
 
   memset(m->m_data, 0, m->m_size);
 
-  m->m_data += IF_MAXLINKHDR;
-  tp = (void *)m->m_data;
-  m->m_data += sizeof(struct udpiphdr);
+  tp = tftp_prep_mbuf_data(spt, m);
 
   tp->tp_op = htons(TFTP_DATA);
   tp->x.tp_data.tp_block_nr = htons((spt->block_nr + 1) & 0xffff);
 
-  saddr.sin_addr = recv_tp->ip.ip_dst;
-  saddr.sin_port = recv_tp->udp.uh_dport;
-
-  daddr.sin_addr = spt->client_ip;
-  daddr.sin_port = spt->client_port;
-
   nobytes = tftp_read_data(spt, spt->block_nr, tp->x.tp_data.tp_buf, 512);
 
   if (nobytes < 0) {
@@ -241,10 +255,8 @@ static void tftp_send_next_block(struct tftp_session *spt,
     return;
   }
 
-  m->m_len = sizeof(struct tftp_t) - (512 - nobytes) -
-        sizeof(struct ip) - sizeof(struct udphdr);
-
-  udp_output(NULL, m, &saddr, &daddr, IPTOS_LOWDELAY);
+  m->m_len = sizeof(struct tftp_t) - (512 - nobytes) - sizeof(struct udphdr);
+  tftp_udp_output(spt, m, recv_tp);
 
   if (nobytes == 512) {
     tftp_session_update(spt);
@@ -256,7 +268,8 @@ static void tftp_send_next_block(struct tftp_session *spt,
   spt->block_nr++;
 }
 
-static void tftp_handle_rrq(Slirp *slirp, struct tftp_t *tp, int pktlen)
+static void tftp_handle_rrq(Slirp *slirp, struct sockaddr_storage *srcsas,
+                            struct tftp_t *tp, int pktlen)
 {
   struct tftp_session *spt;
   int s, k;
@@ -267,12 +280,12 @@ static void tftp_handle_rrq(Slirp *slirp, struct tftp_t *tp, int pktlen)
   int nb_options = 0;
 
   /* check if a session already exists and if so terminate it */
-  s = tftp_session_find(slirp, tp);
+  s = tftp_session_find(slirp, srcsas, tp);
   if (s >= 0) {
     tftp_session_terminate(&slirp->tftp_sessions[s]);
   }
 
-  s = tftp_session_allocate(slirp, tp);
+  s = tftp_session_allocate(slirp, srcsas, tp);
 
   if (s < 0) {
     return;
@@ -397,11 +410,12 @@ static void tftp_handle_rrq(Slirp *slirp, struct tftp_t *tp, int pktlen)
   tftp_send_next_block(spt, tp);
 }
 
-static void tftp_handle_ack(Slirp *slirp, struct tftp_t *tp, int pktlen)
+static void tftp_handle_ack(Slirp *slirp, struct sockaddr_storage *srcsas,
+                            struct tftp_t *tp, int pktlen)
 {
   int s;
 
-  s = tftp_session_find(slirp, tp);
+  s = tftp_session_find(slirp, srcsas, tp);
 
   if (s < 0) {
     return;
@@ -410,11 +424,12 @@ static void tftp_handle_ack(Slirp *slirp, struct tftp_t *tp, int pktlen)
   tftp_send_next_block(&slirp->tftp_sessions[s], tp);
 }
 
-static void tftp_handle_error(Slirp *slirp, struct tftp_t *tp, int pktlen)
+static void tftp_handle_error(Slirp *slirp, struct sockaddr_storage *srcsas,
+                              struct tftp_t *tp, int pktlen)
 {
   int s;
 
-  s = tftp_session_find(slirp, tp);
+  s = tftp_session_find(slirp, srcsas, tp);
 
   if (s < 0) {
     return;
@@ -423,21 +438,21 @@ static void tftp_handle_error(Slirp *slirp, struct tftp_t *tp, int pktlen)
   tftp_session_terminate(&slirp->tftp_sessions[s]);
 }
 
-void tftp_input(struct mbuf *m)
+void tftp_input(struct sockaddr_storage *srcsas, struct mbuf *m)
 {
   struct tftp_t *tp = (struct tftp_t *)m->m_data;
 
   switch(ntohs(tp->tp_op)) {
   case TFTP_RRQ:
-    tftp_handle_rrq(m->slirp, tp, m->m_len);
+    tftp_handle_rrq(m->slirp, srcsas, tp, m->m_len);
     break;
 
   case TFTP_ACK:
-    tftp_handle_ack(m->slirp, tp, m->m_len);
+    tftp_handle_ack(m->slirp, srcsas, tp, m->m_len);
     break;
 
   case TFTP_ERROR:
-    tftp_handle_error(m->slirp, tp, m->m_len);
+    tftp_handle_error(m->slirp, srcsas, tp, m->m_len);
     break;
   }
 }
diff --git a/slirp/tftp.h b/slirp/tftp.h
index e1cc24b..1cb1adf 100644
--- a/slirp/tftp.h
+++ b/slirp/tftp.h
@@ -16,7 +16,6 @@
 #define TFTP_FILENAME_MAX 512
 
 struct tftp_t {
-  struct ip ip;
   struct udphdr udp;
   uint16_t tp_op;
   union {
@@ -30,20 +29,20 @@ struct tftp_t {
     } tp_error;
     char tp_buf[512 + 2];
   } x;
-};
+} __attribute__((packed));
 
 struct tftp_session {
     Slirp *slirp;
     char *filename;
     int fd;
 
-    struct in_addr client_ip;
+    struct sockaddr_storage client_addr;
     uint16_t client_port;
     uint32_t block_nr;
 
     int timestamp;
 };
 
-void tftp_input(struct mbuf *m);
+void tftp_input(struct sockaddr_storage *srcsas, struct mbuf *m);
 
 #endif
diff --git a/slirp/udp.c b/slirp/udp.c
index be012fb..247024f 100644
--- a/slirp/udp.c
+++ b/slirp/udp.c
@@ -128,6 +128,11 @@ udp_input(register struct mbuf *m, int iphlen)
 	  }
 	}
 
+	lhost.ss_family = AF_INET;
+	lhost4 = (struct sockaddr_in *) &lhost;
+	lhost4->sin_addr = ip->ip_src;
+	lhost4->sin_port = uh->uh_sport;
+
         /*
          *  handle DHCP/BOOTP
          */
@@ -143,7 +148,11 @@ udp_input(register struct mbuf *m, int iphlen)
          */
         if (ntohs(uh->uh_dport) == TFTP_SERVER &&
             ip->ip_dst.s_addr == slirp->vhost_addr.s_addr) {
-            tftp_input(m);
+            m->m_data += iphlen;
+            m->m_len -= iphlen;
+            tftp_input(&lhost, m);
+            m->m_data -= iphlen;
+            m->m_len += iphlen;
             goto bad;
         }
 
@@ -154,11 +163,6 @@ udp_input(register struct mbuf *m, int iphlen)
 	/*
 	 * Locate pcb for datagram.
 	 */
-	lhost.ss_family = AF_INET;
-	lhost4 = (struct sockaddr_in *) &lhost;
-	lhost4->sin_addr = ip->ip_src;
-	lhost4->sin_port = uh->uh_sport;
-
 	so = solookup(&slirp->udp_last_so, &slirp->udb, &lhost, NULL);
 
 	if (so == NULL) {
diff --git a/slirp/udp6.c b/slirp/udp6.c
index 8952de2..690c4e1 100644
--- a/slirp/udp6.c
+++ b/slirp/udp6.c
@@ -55,14 +55,24 @@ void udp6_input(struct mbuf *m)
      */
     save_ip = *ip;
 
-    /* TODO handle DHCP/BOOTP */
-    /* TODO handle TFTP */
-
     /* Locate pcb for datagram. */
     lhost.sin6_family = AF_INET6;
     lhost.sin6_addr = ip->ip_src;
     lhost.sin6_port = uh->uh_sport;
 
+    /* TODO handle DHCP/BOOTP */
+
+    /* handle TFTP */
+    if (ntohs(uh->uh_dport) == TFTP_SERVER &&
+        !memcmp(ip->ip_dst.s6_addr, slirp->vhost_addr6.s6_addr, 16)) {
+        m->m_data += hlen;
+        m->m_len -= hlen;
+        tftp_input((struct sockaddr_storage *)&lhost, m);
+        m->m_data -= hlen;
+        m->m_len += hlen;
+        goto bad;
+    }
+
     so = solookup(&slirp->udp_last_so, &slirp->udb,
                   (struct sockaddr_storage *) &lhost, NULL);
 
-- 
2.7.0

^ permalink raw reply related	[flat|nested] 51+ messages in thread

* Re: [Qemu-devel] [PATCHv9 04/10] slirp: Factorizing tcpiphdr structure with an union
  2016-02-22 19:28 ` [Qemu-devel] [PATCHv9 04/10] slirp: Factorizing tcpiphdr structure with an union Samuel Thibault
@ 2016-02-23  8:07   ` Thomas Huth
  0 siblings, 0 replies; 51+ messages in thread
From: Thomas Huth @ 2016-02-23  8:07 UTC (permalink / raw)
  To: Samuel Thibault, qemu-devel
  Cc: zhanghailiang, Li Zhijian, Stefan Hajnoczi, Jason Wang,
	Dave Gilbert, Vasiliy Tolstov, Huangpeng, Gonglei, Jan Kiszka,
	Guillaume Subiron

On 22.02.2016 20:28, Samuel Thibault wrote:
> From: Guillaume Subiron <maethor@subiron.org>
> 
> This patch factorizes the tcpiphdr structure to put the IPv4 fields in
> an union, for addition of version 6 in further patch.
> Using some macros, retrocompatibility of the existing code is assured.
> 
> This patch also fixes the SLIRP_MSIZE and margin computation in various
> functions, and makes them compatible with the new tcpiphdr structure,
> whose size will be bigger than sizeof(struct tcphdr) + sizeof(struct ip)
> 
> Signed-off-by: Guillaume Subiron <maethor@subiron.org>
> Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
> ---
>  slirp/if.h         |  4 ++--
>  slirp/mbuf.c       |  4 ++--
>  slirp/slirp.c      | 15 ++++++++-------
>  slirp/socket.c     | 13 ++++++++++++-
>  slirp/tcp_input.c  | 31 ++++++++++++++++++++-----------
>  slirp/tcp_output.c | 18 +++++++++++++-----
>  slirp/tcp_subr.c   | 31 ++++++++++++++++++++++---------
>  slirp/tcpip.h      | 31 +++++++++++++++++++++++--------
>  8 files changed, 102 insertions(+), 45 deletions(-)

Sounds reasonable to me now.

Reviewed-by: Thomas Huth <thuth@redhat.com>

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [Qemu-devel] [PATCHv9 08/10] slirp: Adding IPv6 address for DNS relay
  2016-02-22 19:28 ` [Qemu-devel] [PATCHv9 08/10] slirp: Adding IPv6 address for DNS relay Samuel Thibault
@ 2016-02-23  8:12   ` Thomas Huth
  0 siblings, 0 replies; 51+ messages in thread
From: Thomas Huth @ 2016-02-23  8:12 UTC (permalink / raw)
  To: Samuel Thibault, qemu-devel
  Cc: zhanghailiang, Li Zhijian, Stefan Hajnoczi, Jason Wang,
	Dave Gilbert, Vasiliy Tolstov, Huangpeng, Gonglei, Jan Kiszka,
	Guillaume Subiron

On 22.02.2016 20:28, Samuel Thibault wrote:
> From: Guillaume Subiron <maethor@subiron.org>
> 
> This patch adds an IPv6 address to the DNS relay. in6_equal_dns() is
> developed using this Slirp attribute.
> sotranslate_in/out/accept() are also updated to manage the IPv6 case so the
> guest can be able to join the host using one of the Slirp addresses.
> 
> For now this only points to localhost. Further development will be needed to
> automatically fetch the IPv6 address from resolv.conf, and announce this via
> RDNSS.
> 
> Signed-off-by: Guillaume Subiron <maethor@subiron.org>
> Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
> ---
>  slirp/ip6.h    |  6 +++++-
>  slirp/slirp.c  |  1 +
>  slirp/slirp.h  |  1 +
>  slirp/socket.c | 32 ++++++++++++++++++++++++++++++++
>  4 files changed, 39 insertions(+), 1 deletion(-)

Reviewed-by: Thomas Huth <thuth@redhat.com>

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [Qemu-devel] [PATCHv9 09/10] qapi-schema, qemu-options & slirp: Adding Qemu options for IPv6 addresses
  2016-02-22 19:28 ` [Qemu-devel] [PATCHv9 09/10] qapi-schema, qemu-options & slirp: Adding Qemu options for IPv6 addresses Samuel Thibault
@ 2016-02-23  8:27   ` Thomas Huth
  2016-03-07  7:05   ` Jason Wang
  1 sibling, 0 replies; 51+ messages in thread
From: Thomas Huth @ 2016-02-23  8:27 UTC (permalink / raw)
  To: Samuel Thibault, qemu-devel
  Cc: zhanghailiang, Li Zhijian, Stefan Hajnoczi, Jason Wang,
	Dave Gilbert, Vasiliy Tolstov, Huangpeng, Yann Bordenave,
	Gonglei, Jan Kiszka, Guillaume Subiron

On 22.02.2016 20:28, Samuel Thibault wrote:
> From: Yann Bordenave <meow@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 <meow@meowstars.org>
> Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
> ---
>  net/net.c        | 31 +++++++++++++++++++++++++
>  net/slirp.c      | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++-----
>  qapi-schema.json | 40 ++++++++++++++++++++------------
>  qemu-options.hx  | 18 +++++++++++++--
>  slirp/libslirp.h |  8 ++++---
>  slirp/slirp.c    | 16 +++++++------
>  6 files changed, 150 insertions(+), 32 deletions(-)
...
> diff --git a/net/slirp.c b/net/slirp.c
> index 6b51fbc..bd712bc 100644
> --- a/net/slirp.c
> +++ b/net/slirp.c
> @@ -36,6 +36,7 @@
>  #include "qemu/error-report.h"
>  #include "qemu/sockets.h"
>  #include "slirp/libslirp.h"
> +#include "slirp/ip6.h"
>  #include "sysemu/char.h"
>  
>  static int get_str_sep(char *buf, int buf_size, const char **pp, int sep)
> @@ -135,10 +136,13 @@ 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 */
> @@ -146,6 +150,9 @@ 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 in6_addr ip6_prefix;
> +    struct in6_addr ip6_host;
> +    struct in6_addr ip6_dns;
>  #ifndef _WIN32
>      struct in_addr smbsrv = { .s_addr = 0 };
>  #endif
> @@ -235,6 +242,52 @@ static int net_slirp_init(NetClientState *peer, const char *model,
>      }
>  #endif
>  
> +
> +    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;
> +    }

I think you could also immediately check for vprefix6_len > 126 here
already, then you could drop the two checks for 126 below. A prefix that
is bigger than 126 does not make much sense anyway, so I think it should
be ok to always disallow this (especially since there will be at least
three hosts in this network - the host, the guest, and the DNS server).

> +    if (vhost6) {
> +        if (!inet_pton(AF_INET6, vhost6, &ip6_host)) {
> +            return -1;
> +        }
> +        if (!in6_equal_net(&ip6_prefix, &ip6_host, vprefix6_len)) {
> +            return -1;
> +        }
> +    } else {
> +        if (vprefix6_len > 126) {
> +            return -1;
> +        }
> +        ip6_host = ip6_prefix;
> +        ip6_host.s6_addr[15] |= 2;
> +    }
> +
> +    if (vnameserver6) {
> +        if (!inet_pton(AF_INET6, vnameserver6, &ip6_dns)) {
> +            return -1;
> +        }
> +        if (!in6_equal_net(&ip6_prefix, &ip6_dns, vprefix6_len)) {
> +            return -1;
> +        }
> +    } else {
> +        if (vprefix6_len > 126) {
> +            return -1;
> +        }
> +        ip6_dns = ip6_prefix;
> +        ip6_dns.s6_addr[15] |= 3;
> +    }

The other parts of the patch looks fine to me now.

 Thomas

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [Qemu-devel] [PATCHv9 0/10] slirp: Adding IPv6 support to Qemu -net user mode
  2016-02-22 19:28 [Qemu-devel] [PATCHv9 0/10] slirp: Adding IPv6 support to Qemu -net user mode Samuel Thibault
                   ` (9 preceding siblings ...)
  2016-02-22 19:28 ` [Qemu-devel] [PATCHv9 10/10] slirp: Add IPv6 support to the TFTP code Samuel Thibault
@ 2016-03-04  8:41 ` Thomas Huth
  2016-03-04 15:50   ` Jan Kiszka
  2016-03-07  6:48 ` Jason Wang
  11 siblings, 1 reply; 51+ messages in thread
From: Thomas Huth @ 2016-03-04  8:41 UTC (permalink / raw)
  To: Samuel Thibault, Jason Wang, Jan Kiszka
  Cc: zhanghailiang, Li Zhijian, Stefan Hajnoczi, Dave Gilbert,
	Vasiliy Tolstov, qemu-devel, Gonglei, Huangpeng,
	Guillaume Subiron

On 22.02.2016 20:28, Samuel Thibault wrote:
> Hello,
> 
> This is another respin of IPv6 in Qemu -net user mode.
> 
> These patches add ICMPv6, NDP, make UDP and TCP compatible with IPv6, and add
> TFTP over IPv6.

*ping*

 Jan, Jason,

could you please have a look at this series? Would be cool to include it
for 2.6 so that we'd finally have IPv6 support in Slirp, too.
As far as I could see, the patches look fine now - there was just one
rather cosmetic issue left in patch 9/10, but it should also be ok in
the current shape already, I think, so IMHO no need for a respin.

 Thomas

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [Qemu-devel] [PATCHv9 0/10] slirp: Adding IPv6 support to Qemu -net user mode
  2016-03-04  8:41 ` [Qemu-devel] [PATCHv9 0/10] slirp: Adding IPv6 support to Qemu -net user mode Thomas Huth
@ 2016-03-04 15:50   ` Jan Kiszka
  2016-03-06 16:59     ` Samuel Thibault
  0 siblings, 1 reply; 51+ messages in thread
From: Jan Kiszka @ 2016-03-04 15:50 UTC (permalink / raw)
  To: Thomas Huth, Samuel Thibault, Jason Wang
  Cc: zhanghailiang, Li Zhijian, Stefan Hajnoczi, Dave Gilbert,
	Vasiliy Tolstov, qemu-devel, Gonglei, Huangpeng,
	Guillaume Subiron

On 2016-03-04 09:41, Thomas Huth wrote:
> On 22.02.2016 20:28, Samuel Thibault wrote:
>> Hello,
>>
>> This is another respin of IPv6 in Qemu -net user mode.
>>
>> These patches add ICMPv6, NDP, make UDP and TCP compatible with IPv6, and add
>> TFTP over IPv6.
> 
> *ping*
> 
>  Jan, Jason,
> 
> could you please have a look at this series? Would be cool to include it
> for 2.6 so that we'd finally have IPv6 support in Slirp, too.
> As far as I could see, the patches look fine now - there was just one
> rather cosmetic issue left in patch 9/10, but it should also be ok in
> the current shape already, I think, so IMHO no need for a respin.

As indicated before, we need someone else than me to manage the slirp
system. I'm out of bandwidth for this task, sorry.

Jan

-- 
Siemens AG, Corporate Technology, CT RDA ITP SES-DE
Corporate Competence Center Embedded Linux

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [Qemu-devel] [PATCHv9 0/10] slirp: Adding IPv6 support to Qemu -net user mode
  2016-03-04 15:50   ` Jan Kiszka
@ 2016-03-06 16:59     ` Samuel Thibault
  2016-03-07  5:03       ` Jason Wang
  0 siblings, 1 reply; 51+ messages in thread
From: Samuel Thibault @ 2016-03-06 16:59 UTC (permalink / raw)
  To: Jan Kiszka
  Cc: Thomas Huth, zhanghailiang, Li Zhijian, Stefan Hajnoczi,
	Jason Wang, qemu-devel, Vasiliy Tolstov, Dave Gilbert, Gonglei,
	Huangpeng, Guillaume Subiron

Hello,

Jan Kiszka, on Fri 04 Mar 2016 16:50:32 +0100, wrote:
> On 2016-03-04 09:41, Thomas Huth wrote:
> > On 22.02.2016 20:28, Samuel Thibault wrote:
> >> Hello,
> >>
> >> This is another respin of IPv6 in Qemu -net user mode.
> >>
> >> These patches add ICMPv6, NDP, make UDP and TCP compatible with IPv6, and add
> >> TFTP over IPv6.
> > 
> > *ping*
> > 
> >  Jan, Jason,
> > 
> > could you please have a look at this series? Would be cool to include it
> > for 2.6 so that we'd finally have IPv6 support in Slirp, too.
> > As far as I could see, the patches look fine now - there was just one
> > rather cosmetic issue left in patch 9/10, but it should also be ok in
> > the current shape already, I think, so IMHO no need for a respin.
> 
> As indicated before, we need someone else than me to manage the slirp
> system. I'm out of bandwidth for this task, sorry.

Ok, Jason?

I'm really surprised that a patch that has been reviewed two times (by
me then by Thomas) seems so difficult to get it.  I understand that
it's far from trivial, but I have concerns with how qemu can manage
contributions.

Samuel

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [Qemu-devel] [PATCHv9 0/10] slirp: Adding IPv6 support to Qemu -net user mode
  2016-03-06 16:59     ` Samuel Thibault
@ 2016-03-07  5:03       ` Jason Wang
  2016-03-07 11:09         ` Samuel Thibault
  0 siblings, 1 reply; 51+ messages in thread
From: Jason Wang @ 2016-03-07  5:03 UTC (permalink / raw)
  To: Samuel Thibault, Jan Kiszka
  Cc: Thomas Huth, zhanghailiang, Li Zhijian, Stefan Hajnoczi,
	Dave Gilbert, Vasiliy Tolstov, qemu-devel, Gonglei, Huangpeng,
	Guillaume Subiron



On 03/07/2016 12:59 AM, Samuel Thibault wrote:
> Hello,
>
> Jan Kiszka, on Fri 04 Mar 2016 16:50:32 +0100, wrote:
>> On 2016-03-04 09:41, Thomas Huth wrote:
>>> On 22.02.2016 20:28, Samuel Thibault wrote:
>>>> Hello,
>>>>
>>>> This is another respin of IPv6 in Qemu -net user mode.
>>>>
>>>> These patches add ICMPv6, NDP, make UDP and TCP compatible with IPv6, and add
>>>> TFTP over IPv6.
>>> *ping*
>>>
>>>  Jan, Jason,
>>>
>>> could you please have a look at this series? Would be cool to include it
>>> for 2.6 so that we'd finally have IPv6 support in Slirp, too.
>>> As far as I could see, the patches look fine now - there was just one
>>> rather cosmetic issue left in patch 9/10, but it should also be ok in
>>> the current shape already, I think, so IMHO no need for a respin.
>> As indicated before, we need someone else than me to manage the slirp
>> system. I'm out of bandwidth for this task, sorry.
> Ok, Jason?
>
> I'm really surprised that a patch that has been reviewed two times (by
> me then by Thomas) seems so difficult to get it.  I understand that
> it's far from trivial, but I have concerns with how qemu can manage
> contributions.
>
> Samuel

Sorry. I wasn't aware of needing a new maintainer for slirp before. Will
look at this series soon and take slirp until we have a new maintainer.

Btw, do you want to be the maintainer of slirp? (Or maybe Tohmas want to
do this?)

Thanks

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [Qemu-devel] [PATCHv9 0/10] slirp: Adding IPv6 support to Qemu -net user mode
  2016-02-22 19:28 [Qemu-devel] [PATCHv9 0/10] slirp: Adding IPv6 support to Qemu -net user mode Samuel Thibault
                   ` (10 preceding siblings ...)
  2016-03-04  8:41 ` [Qemu-devel] [PATCHv9 0/10] slirp: Adding IPv6 support to Qemu -net user mode Thomas Huth
@ 2016-03-07  6:48 ` Jason Wang
  2016-03-07 11:19   ` Samuel Thibault
  2016-03-07 11:55   ` Samuel Thibault
  11 siblings, 2 replies; 51+ messages in thread
From: Jason Wang @ 2016-03-07  6:48 UTC (permalink / raw)
  To: Samuel Thibault, qemu-devel
  Cc: Thomas Huth, zhanghailiang, Li Zhijian, Stefan Hajnoczi,
	Dave Gilbert, Vasiliy Tolstov, Huangpeng, Gonglei, Jan Kiszka,
	Guillaume Subiron



On 02/23/2016 03:28 AM, Samuel Thibault wrote:
> Hello,
>
> This is another respin of IPv6 in Qemu -net user mode.
>
>
> These patches add ICMPv6, NDP, make UDP and TCP compatible with IPv6, and add
> TFTP over IPv6.
>

Thanks a lot for the patches. Looks good overall, but see some issues:

- the series does not build on w32:
In file included from ./slirp/slirp.h:126:0,
                 from stubs/slirp.c:3:
./slirp/ip6.h:9:24: fatal error: netinet/in.h: No such file or directory
compilation terminated.
- Lots of checkpatch warnings, let's try to silent it.
- The patches do not apply to master cleanly.
- I expects a unit-test for this. You may want to have a look at the
pxe-test in tests/, I think it could be extended to test ipv6 slirp somehow.

And also some nits, see individual patches.

> Difference with version 8 is:
> - Fix freeing random number generator
> - Fix coding style
> - Fix prefix lengths in in6_equal_dns macro
>
> Here is a summary of the patches:
> Guillaume Subiron (7):
>   slirp: Adding IPv6, ICMPv6 Echo and NDP autoconfiguration
>   slirp: Adding IPv6 UDP support
>   slirp: Factorizing tcpiphdr structure with an union
>   slirp: Generalizing and neutralizing various TCP functions before
>     adding IPv6 stuff
>   slirp: Reindent after refactoring
>   slirp: Handle IPv6 in TCP functions
>   slirp: Adding IPv6 address for DNS relay
>
> Thomas Huth (1):
>   slirp: Add IPv6 support to the TFTP code
>
> Yann Bordenave (2):
>   slirp: Adding ICMPv6 error sending
>   qapi-schema, qemu-options & slirp: Adding Qemu options for IPv6
>     addresses
>
>  net/net.c           |  31 ++++
>  net/slirp.c         |  69 ++++++++-
>  qapi-schema.json    |  40 +++--
>  qemu-options.hx     |  18 ++-
>  slirp/Makefile.objs |   6 +-
>  slirp/cksum.c       |  25 ++++
>  slirp/if.c          |   2 +-
>  slirp/if.h          |   4 +-
>  slirp/ip6.h         | 142 ++++++++++++++++++
>  slirp/ip6_icmp.c    | 411 ++++++++++++++++++++++++++++++++++++++++++++++++++++
>  slirp/ip6_icmp.h    | 213 +++++++++++++++++++++++++++
>  slirp/ip6_input.c   |  73 ++++++++++
>  slirp/ip6_output.c  |  38 +++++
>  slirp/ip_icmp.c     |  12 +-
>  slirp/ip_icmp.h     |   4 +-
>  slirp/ip_input.c    |  10 +-
>  slirp/libslirp.h    |   8 +-
>  slirp/mbuf.c        |   4 +-
>  slirp/ndp_table.c   |  84 +++++++++++
>  slirp/slirp.c       |  81 +++++++++--
>  slirp/slirp.h       |  43 +++++-
>  slirp/socket.c      |  54 ++++++-
>  slirp/socket.h      |  13 ++
>  slirp/tcp.h         |   2 +
>  slirp/tcp_input.c   | 181 ++++++++++++++++-------
>  slirp/tcp_output.c  |  51 +++++--
>  slirp/tcp_subr.c    | 114 +++++++++++----
>  slirp/tcp_timer.c   |   3 +-
>  slirp/tcpip.h       |  40 ++++-
>  slirp/tftp.c        | 133 +++++++++--------
>  slirp/tftp.h        |   7 +-
>  slirp/udp.c         |  19 ++-
>  slirp/udp.h         |   5 +
>  slirp/udp6.c        | 167 +++++++++++++++++++++
>  34 files changed, 1877 insertions(+), 230 deletions(-)
>  create mode 100644 slirp/ip6.h
>  create mode 100644 slirp/ip6_icmp.c
>  create mode 100644 slirp/ip6_icmp.h
>  create mode 100644 slirp/ip6_input.c
>  create mode 100644 slirp/ip6_output.c
>  create mode 100644 slirp/ndp_table.c
>  create mode 100644 slirp/udp6.c
>

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [Qemu-devel] [PATCHv9 01/10] slirp: Adding IPv6, ICMPv6 Echo and NDP autoconfiguration
  2016-02-22 19:28 ` [Qemu-devel] [PATCHv9 01/10] slirp: Adding IPv6, ICMPv6 Echo and NDP autoconfiguration Samuel Thibault
@ 2016-03-07  6:53   ` Jason Wang
  2016-03-07 11:24     ` Samuel Thibault
  0 siblings, 1 reply; 51+ messages in thread
From: Jason Wang @ 2016-03-07  6:53 UTC (permalink / raw)
  To: Samuel Thibault, qemu-devel
  Cc: Thomas Huth, zhanghailiang, Li Zhijian, Stefan Hajnoczi,
	Dave Gilbert, Vasiliy Tolstov, Huangpeng, Gonglei, Jan Kiszka,
	Guillaume Subiron



On 02/23/2016 03:28 AM, Samuel Thibault wrote:
> From: Guillaume Subiron <maethor@subiron.org>
>
> This patch adds the functions needed to handle IPv6 packets. ICMPv6 and
> NDP headers are implemented.
>
> Slirp is now able to send NDP Router or Neighbor Advertisement when it
> receives Router or Neighbor Solicitation. Using a 64bit-sized IPv6
> prefix, the guest is now able to perform stateless autoconfiguration
> (SLAAC) and to compute its IPv6 address.
>
> This patch adds an ndp_table, mainly inspired by arp_table, to keep an
> NDP cache and manage network address resolution.
> Slirp regularly sends NDP Neighbor Advertisement, as recommended by the
> RFC, to make the guest refresh its route.
>
> This also adds ip6_cksum() to compute ICMPv6 checksums using IPv6
> pseudo-header.
>
> Some #define ETH_* are moved upper in slirp.h to make them accessible to
> other slirp/*.h
>
> Signed-off-by: Guillaume Subiron <maethor@subiron.org>
> Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
> Reviewed-by: Thomas Huth <thuth@redhat.com>
> ---
>  slirp/Makefile.objs |   6 +-
>  slirp/cksum.c       |  25 ++++
>  slirp/if.c          |   2 +-
>  slirp/ip6.h         | 138 +++++++++++++++++++++
>  slirp/ip6_icmp.c    | 347 ++++++++++++++++++++++++++++++++++++++++++++++++++++
>  slirp/ip6_icmp.h    | 203 ++++++++++++++++++++++++++++++
>  slirp/ip6_input.c   |  69 +++++++++++
>  slirp/ip6_output.c  |  38 ++++++
>  slirp/ndp_table.c   |  84 +++++++++++++
>  slirp/slirp.c       |  51 +++++++-
>  slirp/slirp.h       |  37 ++++++
>  slirp/socket.h      |   7 ++
>  12 files changed, 1001 insertions(+), 6 deletions(-)
>  create mode 100644 slirp/ip6.h
>  create mode 100644 slirp/ip6_icmp.c
>  create mode 100644 slirp/ip6_icmp.h
>  create mode 100644 slirp/ip6_input.c
>  create mode 100644 slirp/ip6_output.c
>  create mode 100644 slirp/ndp_table.c
>

[...]

> +
> +    /*
> +     * Switch out to protocol's input routine.
> +     */
> +    switch (ip6->ip_nh) {
> +#if 0
> +    case IPPROTO_TCP:
> +        tcp_input(m, hlen, (struct socket *)NULL);
> +        break;
> +    case IPPROTO_UDP:
> +        udp_input(m, hlen);
> +        break;
> +#endif

This looks odd, why need this?

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [Qemu-devel] [PATCHv9 02/10] slirp: Adding ICMPv6 error sending
  2016-02-22 19:28 ` [Qemu-devel] [PATCHv9 02/10] slirp: Adding ICMPv6 error sending Samuel Thibault
@ 2016-03-07  6:55   ` Jason Wang
  2016-03-07 13:34     ` Samuel Thibault
  0 siblings, 1 reply; 51+ messages in thread
From: Jason Wang @ 2016-03-07  6:55 UTC (permalink / raw)
  To: Samuel Thibault, qemu-devel
  Cc: Thomas Huth, zhanghailiang, Li Zhijian, Stefan Hajnoczi,
	Dave Gilbert, Vasiliy Tolstov, Huangpeng, Yann Bordenave,
	Gonglei, Jan Kiszka, Guillaume Subiron



On 02/23/2016 03:28 AM, Samuel Thibault wrote:
> From: Yann Bordenave <meow@meowstars.org>
>
> Disambiguation : icmp_error is renamed into icmp_send_error, since it
> doesn't manage errors, but only sends ICMP Error messages.
>
> Adding icmp6_send_error to send ICMPv6 Error messages. This function is
> simpler than the v4 version.
> Adding some calls in various functions to send ICMP errors, when a
> received packet is too big, or when its hop limit is 0.

Let's split this into two patches to avoid mixing renaming and new
function introduction.

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [Qemu-devel] [PATCHv9 03/10] slirp: Adding IPv6 UDP support
  2016-02-22 19:28 ` [Qemu-devel] [PATCHv9 03/10] slirp: Adding IPv6 UDP support Samuel Thibault
@ 2016-03-07  6:57   ` Jason Wang
  2016-03-07 11:36     ` Samuel Thibault
  0 siblings, 1 reply; 51+ messages in thread
From: Jason Wang @ 2016-03-07  6:57 UTC (permalink / raw)
  To: Samuel Thibault, qemu-devel
  Cc: Thomas Huth, zhanghailiang, Li Zhijian, Stefan Hajnoczi,
	Dave Gilbert, Vasiliy Tolstov, Huangpeng, Gonglei, Jan Kiszka,
	Guillaume Subiron



On 02/23/2016 03:28 AM, Samuel Thibault wrote:
> From: Guillaume Subiron <maethor@subiron.org>
>
> This adds the sin6 case in the fhost and lhost unions and related macros.
> It adds udp6_input() and udp6_output().
> It adds the IPv6 case in sorecvfrom().
> Finally, udp_input() is called by ip6_input().
>
> Signed-off-by: Guillaume Subiron <maethor@subiron.org>
> Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
> Reviewed-by: Thomas Huth <thuth@redhat.com>
> ---
>  slirp/Makefile.objs |   2 +-
>  slirp/ip6_input.c   |   2 +-
>  slirp/socket.c      |   5 ++
>  slirp/socket.h      |   6 ++
>  slirp/udp.h         |   5 ++
>  slirp/udp6.c        | 157 ++++++++++++++++++++++++++++++++++++++++++++++++++++
>  6 files changed, 175 insertions(+), 2 deletions(-)
>  create mode 100644 slirp/udp6.c
>
> diff --git a/slirp/Makefile.objs b/slirp/Makefile.objs
> index 4e3a289..6748e4f 100644
> --- a/slirp/Makefile.objs
> +++ b/slirp/Makefile.objs
> @@ -1,5 +1,5 @@
>  common-obj-y = cksum.o if.o ip_icmp.o ip6_icmp.o ip6_input.o ip6_output.o \
>                 ip_input.o ip_output.o dnssearch.o
>  common-obj-y += slirp.o mbuf.o misc.o sbuf.o socket.o tcp_input.o tcp_output.o
> -common-obj-y += tcp_subr.o tcp_timer.o udp.o bootp.o tftp.o arp_table.o \
> +common-obj-y += tcp_subr.o tcp_timer.o udp.o udp6.o bootp.o tftp.o arp_table.o \
>                  ndp_table.o
> diff --git a/slirp/ip6_input.c b/slirp/ip6_input.c
> index b6a438d..9ca6d32 100644
> --- a/slirp/ip6_input.c
> +++ b/slirp/ip6_input.c
> @@ -58,7 +58,7 @@ void ip6_input(struct mbuf *m)
>          icmp6_send_error(m, ICMP6_UNREACH, ICMP6_UNREACH_NO_ROUTE);
>          break;
>      case IPPROTO_UDP:
> -        icmp6_send_error(m, ICMP6_UNREACH, ICMP6_UNREACH_NO_ROUTE);
> +        udp6_input(m);
>          break;
>      case IPPROTO_ICMPV6:
>          icmp6_input(m);
> diff --git a/slirp/socket.c b/slirp/socket.c
> index 32b1ba3..b79ddec 100644
> --- a/slirp/socket.c
> +++ b/slirp/socket.c
> @@ -541,7 +541,12 @@ sorecvfrom(struct socket *so)
>  	                   (struct sockaddr_in *) &daddr,
>  	                   so->so_iptos);
>  	        break;
> +	    case AF_INET6:
> +	        udp6_output(so, m, (struct sockaddr_in6 *) &saddr,
> +	                    (struct sockaddr_in6 *) &daddr);
> +	        break;
>  	    default:
> +	        g_assert_not_reached();
>  	        break;
>  	    }
>  	  } /* rx error */
> diff --git a/slirp/socket.h b/slirp/socket.h
> index bcebce1..e9c9b05 100644
> --- a/slirp/socket.h
> +++ b/slirp/socket.h
> @@ -34,17 +34,23 @@ struct socket {
>    union {   /* foreign host */
>        struct sockaddr_storage ss;
>        struct sockaddr_in sin;
> +      struct sockaddr_in6 sin6;
>    } fhost;
>  #define so_faddr fhost.sin.sin_addr
>  #define so_fport fhost.sin.sin_port
> +#define so_faddr6 fhost.sin6.sin6_addr
> +#define so_fport6 fhost.sin6.sin6_port
>  #define so_ffamily fhost.ss.ss_family
>  
>    union {   /* local host */
>        struct sockaddr_storage ss;
>        struct sockaddr_in sin;
> +      struct sockaddr_in6 sin6;
>    } lhost;
>  #define so_laddr lhost.sin.sin_addr
>  #define so_lport lhost.sin.sin_port
> +#define so_laddr6 lhost.sin6.sin6_addr
> +#define so_lport6 lhost.sin6.sin6_port
>  #define so_lfamily lhost.ss.ss_family
>  
>    uint8_t	so_iptos;	/* Type of service */
> diff --git a/slirp/udp.h b/slirp/udp.h
> index 2f9de38..10cc780 100644
> --- a/slirp/udp.h
> +++ b/slirp/udp.h
> @@ -83,4 +83,9 @@ struct socket * udp_listen(Slirp *, uint32_t, u_int, uint32_t, u_int,
>  int udp_output(struct socket *so, struct mbuf *m,
>                  struct sockaddr_in *saddr, struct sockaddr_in *daddr,
>                  int iptos);
> +
> +void udp6_input(register struct mbuf *);
> +int udp6_output(struct socket *so, struct mbuf *m,
> +                struct sockaddr_in6 *saddr, struct sockaddr_in6 *daddr);
> +
>  #endif
> diff --git a/slirp/udp6.c b/slirp/udp6.c
> new file mode 100644
> index 0000000..8952de2
> --- /dev/null
> +++ b/slirp/udp6.c
> @@ -0,0 +1,157 @@
> +/*
> + * Copyright (c) 2013
> + * Guillaume Subiron
> + */
> +
> +#include "slirp.h"
> +#include "qemu/osdep.h"
> +#include "udp.h"
> +
> +void udp6_input(struct mbuf *m)
> +{
> +    Slirp *slirp = m->slirp;
> +    struct ip6 *ip, save_ip;
> +    struct udphdr *uh;
> +    int hlen = sizeof(struct ip6);
> +    int len;
> +    struct socket *so;
> +    struct sockaddr_in6 lhost;
> +
> +    DEBUG_CALL("udp6_input");
> +    DEBUG_ARG("m = %lx", (long)m);
> +
> +    if (slirp->restricted) {
> +        goto bad;
> +    }
> +
> +    ip = mtod(m, struct ip6 *);
> +    m->m_len -= hlen;
> +    m->m_data += hlen;
> +    uh = mtod(m, struct udphdr *);
> +    m->m_len += hlen;
> +    m->m_data -= hlen;
> +
> +    if (ip6_cksum(m)) {
> +        goto bad;
> +    }
> +
> +    len = ntohs((uint16_t)uh->uh_ulen);
> +
> +    /*
> +     * Make mbuf data length reflect UDP length.
> +     * If not enough data to reflect UDP length, drop.
> +     */
> +    if (ntohs(ip->ip_pl) != len) {
> +        if (len > ntohs(ip->ip_pl)) {
> +            goto bad;
> +        }
> +        m_adj(m, len - ntohs(ip->ip_pl));
> +        ip->ip_pl = htons(len);
> +    }
> +
> +    /*
> +     * Save a copy of the IP header in case we want restore it
> +     * for sending an ICMP error message in response.
> +     */
> +    save_ip = *ip;
> +
> +    /* TODO handle DHCP/BOOTP */
> +    /* TODO handle TFTP */
> +
> +    /* Locate pcb for datagram. */
> +    lhost.sin6_family = AF_INET6;
> +    lhost.sin6_addr = ip->ip_src;
> +    lhost.sin6_port = uh->uh_sport;
> +
> +    so = solookup(&slirp->udp_last_so, &slirp->udb,
> +                  (struct sockaddr_storage *) &lhost, NULL);
> +
> +    if (so == NULL) {
> +        /* If there's no socket for this packet, create one. */
> +        so = socreate(slirp);
> +        if (!so) {
> +            goto bad;
> +        }
> +        if (udp_attach(so, AF_INET6) == -1) {
> +            DEBUG_MISC((dfd, " udp6_attach errno = %d-%s\n",
> +                        errno, strerror(errno)));
> +            sofree(so);
> +            goto bad;
> +        }
> +
> +        /* Setup fields */
> +        so->so_lfamily = AF_INET6;
> +        so->so_laddr6 = ip->ip_src;
> +        so->so_lport6 = uh->uh_sport;
> +    }
> +
> +    so->so_ffamily = AF_INET6;
> +    so->so_faddr6 = ip->ip_dst; /* XXX */
> +    so->so_fport6 = uh->uh_dport; /* XXX */
> +
> +    hlen += sizeof(struct udphdr);
> +    m->m_len -= hlen;
> +    m->m_data += hlen;
> +
> +    /*
> +     * Now we sendto() the packet.
> +     */
> +    if (sosendto(so, m) == -1) {
> +        m->m_len += hlen;
> +        m->m_data -= hlen;
> +        *ip = save_ip;
> +        DEBUG_MISC((dfd, "udp tx errno = %d-%s\n", errno, strerror(errno)));
> +        /* TODO: ICMPv6 error */
> +        /*icmp_error(m, ICMP_UNREACH,ICMP_UNREACH_NET, 0,strerror(errno));*/
> +        goto bad;
> +    }
> +
> +    m_free(so->so_m);   /* used for ICMP if error on sorecvfrom */
> +
> +    /* restore the orig mbuf packet */
> +    m->m_len += hlen;
> +    m->m_data -= hlen;
> +    *ip = save_ip;
> +    so->so_m = m;
> +
> +    return;
> +bad:
> +    m_free(m);
> +}

Part of the codes looks duplicated with ipv4 version. Any chances to
merge them like tcp?

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [Qemu-devel] [PATCHv9 06/10] slirp: Reindent after refactoring
  2016-02-22 19:28 ` [Qemu-devel] [PATCHv9 06/10] slirp: Reindent after refactoring Samuel Thibault
@ 2016-03-07  7:02   ` Jason Wang
  2016-03-07 11:38     ` Samuel Thibault
  0 siblings, 1 reply; 51+ messages in thread
From: Jason Wang @ 2016-03-07  7:02 UTC (permalink / raw)
  To: Samuel Thibault, qemu-devel
  Cc: Thomas Huth, zhanghailiang, Li Zhijian, Stefan Hajnoczi,
	Dave Gilbert, Vasiliy Tolstov, Huangpeng, Gonglei, Jan Kiszka,
	Guillaume Subiron



On 02/23/2016 03:28 AM, Samuel Thibault wrote:
> From: Guillaume Subiron <maethor@subiron.org>
>
> No code change.
>
> Signed-off-by: Guillaume Subiron <maethor@subiron.org>
> Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
> Reviewed-by: Thomas Huth <thuth@redhat.com>
> ---
>  slirp/tcp_input.c  | 92 +++++++++++++++++++++++++++---------------------------
>  slirp/tcp_output.c | 29 +++++++++--------
>  slirp/tcp_subr.c   | 50 ++++++++++++++---------------

How about other files in slirp/ ?

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [Qemu-devel] [PATCHv9 09/10] qapi-schema, qemu-options & slirp: Adding Qemu options for IPv6 addresses
  2016-02-22 19:28 ` [Qemu-devel] [PATCHv9 09/10] qapi-schema, qemu-options & slirp: Adding Qemu options for IPv6 addresses Samuel Thibault
  2016-02-23  8:27   ` Thomas Huth
@ 2016-03-07  7:05   ` Jason Wang
  2016-03-07 11:39     ` Samuel Thibault
  2016-03-07 11:41     ` Samuel Thibault
  1 sibling, 2 replies; 51+ messages in thread
From: Jason Wang @ 2016-03-07  7:05 UTC (permalink / raw)
  To: Samuel Thibault, qemu-devel
  Cc: Thomas Huth, zhanghailiang, Li Zhijian, Stefan Hajnoczi,
	Dave Gilbert, Vasiliy Tolstov, Huangpeng, Yann Bordenave,
	Gonglei, Jan Kiszka, Guillaume Subiron



On 02/23/2016 03:28 AM, Samuel Thibault wrote:
> From: Yann Bordenave <meow@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 <meow@meowstars.org>
> Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
> ---
>  net/net.c        | 31 +++++++++++++++++++++++++
>  net/slirp.c      | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++-----
>  qapi-schema.json | 40 ++++++++++++++++++++------------
>  qemu-options.hx  | 18 +++++++++++++--
>  slirp/libslirp.h |  8 ++++---
>  slirp/slirp.c    | 16 +++++++------
>  6 files changed, 150 insertions(+), 32 deletions(-)
>
> diff --git a/net/net.c b/net/net.c
> index aebf753..d67904f 100644

[...]

>  
>      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'] } }

Please do unnecessary changes like this since it will cause extra effort
for git blame and other things.

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [Qemu-devel] [PATCHv9 0/10] slirp: Adding IPv6 support to Qemu -net user mode
  2016-03-07  5:03       ` Jason Wang
@ 2016-03-07 11:09         ` Samuel Thibault
  2016-03-07 12:06           ` Jan Kiszka
  2016-03-08  1:37           ` Jason Wang
  0 siblings, 2 replies; 51+ messages in thread
From: Samuel Thibault @ 2016-03-07 11:09 UTC (permalink / raw)
  To: Jason Wang
  Cc: Thomas Huth, zhanghailiang, Li Zhijian, Stefan Hajnoczi,
	qemu-devel, Vasiliy Tolstov, Dave Gilbert, Gonglei, Jan Kiszka,
	Huangpeng, Guillaume Subiron

Jason Wang, on Mon 07 Mar 2016 13:03:11 +0800, wrote:
> Btw, do you want to be the maintainer of slirp? (Or maybe Tohmas want to
> do this?)

I already said I was fine with it, yes, and submitted a MAINTAINERS
patch towards that, without any response.

Samuel

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [Qemu-devel] [PATCHv9 0/10] slirp: Adding IPv6 support to Qemu -net user mode
  2016-03-07  6:48 ` Jason Wang
@ 2016-03-07 11:19   ` Samuel Thibault
  2016-03-07 12:00     ` Thomas Huth
  2016-03-08  2:48     ` Jason Wang
  2016-03-07 11:55   ` Samuel Thibault
  1 sibling, 2 replies; 51+ messages in thread
From: Samuel Thibault @ 2016-03-07 11:19 UTC (permalink / raw)
  To: Jason Wang
  Cc: Thomas Huth, zhanghailiang, Li Zhijian, Stefan Hajnoczi,
	Dave Gilbert, Vasiliy Tolstov, qemu-devel, Gonglei, Jan Kiszka,
	Huangpeng, Guillaume Subiron

Jason Wang, on Mon 07 Mar 2016 14:48:16 +0800, wrote:
> - Lots of checkpatch warnings, let's try to silent it.

They are indentation issues, yes. They are already existing in slirp/
. Whenever new code was added we sticked with the qemu style, but for
patched code we prefered to stick to the existing indentation, since
otherwise it'd mean reindenting it all to keep the functions readable at
all. Do you what to see the whole slirp directory be reindented once for
good before this gets applied? Personally I just don't care which way or
the other.

> - The patches do not apply to master cleanly.

It did at the time I sent them...

> - I expects a unit-test for this. You may want to have a look at the
> pxe-test in tests/, I think it could be extended to test ipv6 slirp somehow.

It doesn't seem so simple to me. In the case of PXE, you have a guest
implementation of PXE inside the BIOS. In the case of IPv6, I don't
think you have a guest implementation of IPv6 in the BIOS... So we'd
need to embed some guest that would do the IPv6 stuff. At best we can
make a qtest_start(), and that's about it.

I'm awfully tired of all of this. This work has been done 3 years ago,
has already seen 9 iterations. Had it not been something important to
my eyes (being able to easily test ipv6), I would have abandoned a long
time ago.

At the university of Bordeaux, we are planning to add a FOSS course with
students participating to existing FOSS projects. I'm afraid we will
just not be able to make them work on qemu at all.

Samuel

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [Qemu-devel] [PATCHv9 01/10] slirp: Adding IPv6, ICMPv6 Echo and NDP autoconfiguration
  2016-03-07  6:53   ` Jason Wang
@ 2016-03-07 11:24     ` Samuel Thibault
  2016-03-08  1:39       ` Jason Wang
  0 siblings, 1 reply; 51+ messages in thread
From: Samuel Thibault @ 2016-03-07 11:24 UTC (permalink / raw)
  To: Jason Wang
  Cc: Thomas Huth, zhanghailiang, Li Zhijian, Stefan Hajnoczi,
	Dave Gilbert, Vasiliy Tolstov, qemu-devel, Gonglei, Jan Kiszka,
	Huangpeng, Guillaume Subiron

Jason Wang, on Mon 07 Mar 2016 14:53:54 +0800, wrote:
> > +    switch (ip6->ip_nh) {
> > +#if 0
> > +    case IPPROTO_TCP:
> > +        tcp_input(m, hlen, (struct socket *)NULL);
> > +        break;
> > +    case IPPROTO_UDP:
> > +        udp_input(m, hlen);
> > +        break;
> > +#endif
> 
> This looks odd, why need this?

To pave the way for the patches after that. We can drop that from this
patch and move to the other ones if you will, I just believe it makes
reading this one easier since it explains how tcp and udp will be
plugged here.

Samuel

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [Qemu-devel] [PATCHv9 03/10] slirp: Adding IPv6 UDP support
  2016-03-07  6:57   ` Jason Wang
@ 2016-03-07 11:36     ` Samuel Thibault
  2016-03-08  1:40       ` Jason Wang
  0 siblings, 1 reply; 51+ messages in thread
From: Samuel Thibault @ 2016-03-07 11:36 UTC (permalink / raw)
  To: Jason Wang
  Cc: Thomas Huth, zhanghailiang, Li Zhijian, Stefan Hajnoczi,
	Dave Gilbert, Vasiliy Tolstov, qemu-devel, Gonglei, Jan Kiszka,
	Huangpeng, Guillaume Subiron

Jason Wang, on Mon 07 Mar 2016 14:57:11 +0800, wrote:
> Part of the codes looks duplicated with ipv4 version. Any chances to
> merge them like tcp?

The duplication is actually quite small: accessing the ip length
is different, filling the address is different, etc.  So there are
differences all along the code.  Is it really worth the factorization?
It seems to me that it would actually *reduce* lisibility.

Samuel

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [Qemu-devel] [PATCHv9 06/10] slirp: Reindent after refactoring
  2016-03-07  7:02   ` Jason Wang
@ 2016-03-07 11:38     ` Samuel Thibault
  2016-03-08  1:43       ` Jason Wang
  0 siblings, 1 reply; 51+ messages in thread
From: Samuel Thibault @ 2016-03-07 11:38 UTC (permalink / raw)
  To: Jason Wang
  Cc: Thomas Huth, zhanghailiang, Li Zhijian, Stefan Hajnoczi,
	Dave Gilbert, Vasiliy Tolstov, qemu-devel, Gonglei, Jan Kiszka,
	Huangpeng, Guillaume Subiron

Jason Wang, on Mon 07 Mar 2016 15:02:53 +0800, wrote:
> On 02/23/2016 03:28 AM, Samuel Thibault wrote:
> > From: Guillaume Subiron <maethor@subiron.org>
> >
> > No code change.
> >
> > Signed-off-by: Guillaume Subiron <maethor@subiron.org>
> > Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
> > Reviewed-by: Thomas Huth <thuth@redhat.com>
> > ---
> >  slirp/tcp_input.c  | 92 +++++++++++++++++++++++++++---------------------------
> >  slirp/tcp_output.c | 29 +++++++++--------
> >  slirp/tcp_subr.c   | 50 ++++++++++++++---------------
> 
> How about other files in slirp/ ?

What do you mean?  This patch is just meant to reindent the code after
'if's and 'case's have been added without reindentation to make it more
readable.

Do you mean reindenting the whole slirp?  That's quite another work...

Samuel

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [Qemu-devel] [PATCHv9 09/10] qapi-schema, qemu-options & slirp: Adding Qemu options for IPv6 addresses
  2016-03-07  7:05   ` Jason Wang
@ 2016-03-07 11:39     ` Samuel Thibault
  2016-03-07 11:41     ` Samuel Thibault
  1 sibling, 0 replies; 51+ messages in thread
From: Samuel Thibault @ 2016-03-07 11:39 UTC (permalink / raw)
  To: Jason Wang
  Cc: Thomas Huth, zhanghailiang, Li Zhijian, Stefan Hajnoczi,
	qemu-devel, Vasiliy Tolstov, Dave Gilbert, Yann Bordenave,
	Gonglei, Jan Kiszka, Huangpeng, Guillaume Subiron

Jason Wang, on Mon 07 Mar 2016 15:05:05 +0800, wrote:
> Please do unnecessary changes like this since it will cause extra effort
> for git blame and other things.

Which is exactly why we avoided to fix all the checkpatch warnings by
leaving existing non-qemu-style indentation.

Samuel

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [Qemu-devel] [PATCHv9 09/10] qapi-schema, qemu-options & slirp: Adding Qemu options for IPv6 addresses
  2016-03-07  7:05   ` Jason Wang
  2016-03-07 11:39     ` Samuel Thibault
@ 2016-03-07 11:41     ` Samuel Thibault
  2016-03-07 16:05       ` Eric Blake
  1 sibling, 1 reply; 51+ messages in thread
From: Samuel Thibault @ 2016-03-07 11:41 UTC (permalink / raw)
  To: Jason Wang
  Cc: Thomas Huth, zhanghailiang, Li Zhijian, Stefan Hajnoczi,
	qemu-devel, Vasiliy Tolstov, Dave Gilbert, Yann Bordenave,
	Gonglei, Jan Kiszka, Huangpeng, Guillaume Subiron

Jason Wang, on Mon 07 Mar 2016 15:05:05 +0800, wrote:
> Please do unnecessary changes like this since it will cause extra effort
> for git blame and other things.

Ok. I just do hope that no other reviewer will come and say that we
should fix the alignment of the parameters.

Samuel

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [Qemu-devel] [PATCHv9 0/10] slirp: Adding IPv6 support to Qemu -net user mode
  2016-03-07  6:48 ` Jason Wang
  2016-03-07 11:19   ` Samuel Thibault
@ 2016-03-07 11:55   ` Samuel Thibault
  2016-03-07 15:37     ` Thomas Huth
  2016-03-08  2:15     ` Jason Wang
  1 sibling, 2 replies; 51+ messages in thread
From: Samuel Thibault @ 2016-03-07 11:55 UTC (permalink / raw)
  To: Jason Wang
  Cc: Thomas Huth, zhanghailiang, Li Zhijian, Stefan Hajnoczi,
	Dave Gilbert, Vasiliy Tolstov, qemu-devel, Gonglei, Jan Kiszka,
	Huangpeng, Guillaume Subiron

Jason Wang, on Mon 07 Mar 2016 14:48:16 +0800, wrote:
> - the series does not build on w32:
> In file included from ./slirp/slirp.h:126:0,
>                  from stubs/slirp.c:3:
> ./slirp/ip6.h:9:24: fatal error: netinet/in.h: No such file or directory

Is it the only issue?  Does it build if you add #ifndef _WIN32 around
that include?

Samuel

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [Qemu-devel] [PATCHv9 0/10] slirp: Adding IPv6 support to Qemu -net user mode
  2016-03-07 11:19   ` Samuel Thibault
@ 2016-03-07 12:00     ` Thomas Huth
  2016-03-07 13:37       ` Samuel Thibault
  2016-03-08  2:48     ` Jason Wang
  1 sibling, 1 reply; 51+ messages in thread
From: Thomas Huth @ 2016-03-07 12:00 UTC (permalink / raw)
  To: Samuel Thibault, Jason Wang
  Cc: zhanghailiang, Li Zhijian, Stefan Hajnoczi, Dave Gilbert,
	Vasiliy Tolstov, qemu-devel, Gonglei, Jan Kiszka, Huangpeng,
	Guillaume Subiron

On 07.03.2016 12:19, Samuel Thibault wrote:
> Jason Wang, on Mon 07 Mar 2016 14:48:16 +0800, wrote:
>> - Lots of checkpatch warnings, let's try to silent it.
> 
> They are indentation issues, yes. They are already existing in slirp/
> . Whenever new code was added we sticked with the qemu style, but for
> patched code we prefered to stick to the existing indentation, since
> otherwise it'd mean reindenting it all to keep the functions readable at
> all. Do you what to see the whole slirp directory be reindented once for
> good before this gets applied? Personally I just don't care which way or
> the other.

IMHO we should reindent the whole slirp folder to the correct QEMU
coding style at one point in time, or this topic will pop up again and
again for each future patch to the slirp sources in the future.
But I think it should be postponed until the IPv6 patches have been
included to avoid yet another unnecessary reiteration.

>> - I expects a unit-test for this. You may want to have a look at the
>> pxe-test in tests/, I think it could be extended to test ipv6 slirp somehow.
> 
> It doesn't seem so simple to me. In the case of PXE, you have a guest
> implementation of PXE inside the BIOS. In the case of IPv6, I don't
> think you have a guest implementation of IPv6 in the BIOS... So we'd
> need to embed some guest that would do the IPv6 stuff. At best we can
> make a qtest_start(), and that's about it.

Maybe we can use qemu-system-pppc64 for this ... the SLOF firmware has
support for IPv6 already. I can have a look at this if you like.

> I'm awfully tired of all of this. This work has been done 3 years ago,
> has already seen 9 iterations. Had it not been something important to
> my eyes (being able to easily test ipv6), I would have abandoned a long
> time ago.

I can fully understand you ... it's always the problems with parts of
QEMU where there is no active maintainer available - the other parts of
QEMU normally work much better. Since Jan does not have time for slirp
anymore, we really urgently need a new maintainer for that code ... (but
let's discuss that in the other mail thread).

 Thomas

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [Qemu-devel] [PATCHv9 0/10] slirp: Adding IPv6 support to Qemu -net user mode
  2016-03-07 11:09         ` Samuel Thibault
@ 2016-03-07 12:06           ` Jan Kiszka
  2016-03-07 12:11             ` Samuel Thibault
  2016-03-07 12:14             ` Thomas Huth
  2016-03-08  1:37           ` Jason Wang
  1 sibling, 2 replies; 51+ messages in thread
From: Jan Kiszka @ 2016-03-07 12:06 UTC (permalink / raw)
  To: Samuel Thibault, Jason Wang
  Cc: Thomas Huth, zhanghailiang, Li Zhijian, Stefan Hajnoczi,
	Dave Gilbert, Vasiliy Tolstov, qemu-devel, Gonglei, Huangpeng,
	Guillaume Subiron

On 2016-03-07 12:09, Samuel Thibault wrote:
> Jason Wang, on Mon 07 Mar 2016 13:03:11 +0800, wrote:
>> Btw, do you want to be the maintainer of slirp? (Or maybe Tohmas want to
>> do this?)
> 
> I already said I was fine with it, yes, and submitted a MAINTAINERS
> patch towards that, without any response.

Sorry if I should have missed that, you would have my ack. Can you
resend or provide a pointer?

Thanks,
Jan

-- 
Siemens AG, Corporate Technology, CT RDA ITP SES-DE
Corporate Competence Center Embedded Linux

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [Qemu-devel] [PATCHv9 0/10] slirp: Adding IPv6 support to Qemu -net user mode
  2016-03-07 12:06           ` Jan Kiszka
@ 2016-03-07 12:11             ` Samuel Thibault
  2016-03-07 12:14             ` Thomas Huth
  1 sibling, 0 replies; 51+ messages in thread
From: Samuel Thibault @ 2016-03-07 12:11 UTC (permalink / raw)
  To: Jan Kiszka
  Cc: Thomas Huth, zhanghailiang, Li Zhijian, Stefan Hajnoczi,
	Jason Wang, qemu-devel, Vasiliy Tolstov, Dave Gilbert, Gonglei,
	Huangpeng, Guillaume Subiron

Jan Kiszka, on Mon 07 Mar 2016 13:06:20 +0100, wrote:
> On 2016-03-07 12:09, Samuel Thibault wrote:
> > Jason Wang, on Mon 07 Mar 2016 13:03:11 +0800, wrote:
> >> Btw, do you want to be the maintainer of slirp? (Or maybe Tohmas want to
> >> do this?)
> > 
> > I already said I was fine with it, yes, and submitted a MAINTAINERS
> > patch towards that, without any response.
> 
> Sorry if I should have missed that, you would have my ack. Can you
> resend or provide a pointer?

I've resent you the mail dated
Date: Thu, 6 Aug 2015 13:10:14 +0200

Samuel

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [Qemu-devel] [PATCHv9 0/10] slirp: Adding IPv6 support to Qemu -net user mode
  2016-03-07 12:06           ` Jan Kiszka
  2016-03-07 12:11             ` Samuel Thibault
@ 2016-03-07 12:14             ` Thomas Huth
  2016-03-07 12:16               ` Jan Kiszka
  1 sibling, 1 reply; 51+ messages in thread
From: Thomas Huth @ 2016-03-07 12:14 UTC (permalink / raw)
  To: Jan Kiszka, Samuel Thibault, Jason Wang
  Cc: zhanghailiang, Li Zhijian, Stefan Hajnoczi, Dave Gilbert,
	Vasiliy Tolstov, qemu-devel, Gonglei, Paolo Bonzini, Huangpeng,
	Guillaume Subiron

On 07.03.2016 13:06, Jan Kiszka wrote:
> On 2016-03-07 12:09, Samuel Thibault wrote:
>> Jason Wang, on Mon 07 Mar 2016 13:03:11 +0800, wrote:
>>> Btw, do you want to be the maintainer of slirp? (Or maybe Tohmas want to
>>> do this?)
>>
>> I already said I was fine with it, yes, and submitted a MAINTAINERS
>> patch towards that, without any response.
> 
> Sorry if I should have missed that, you would have my ack. Can you
> resend or provide a pointer?

Patch is available here:

https://patchwork.ozlabs.org/patch/504661/

It has even been ack'd by Stefan at that point in time. Could somebody
from the maintainers please pick this patch up? Jason (via net)? Paolo
(via misc)? Jan (via slirp), if you can find some spare minutes?

 Thomas

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [Qemu-devel] [PATCHv9 0/10] slirp: Adding IPv6 support to Qemu -net user mode
  2016-03-07 12:14             ` Thomas Huth
@ 2016-03-07 12:16               ` Jan Kiszka
  2016-03-08  2:50                 ` Jason Wang
  0 siblings, 1 reply; 51+ messages in thread
From: Jan Kiszka @ 2016-03-07 12:16 UTC (permalink / raw)
  To: Thomas Huth, Samuel Thibault, Jason Wang, Peter Maydell
  Cc: zhanghailiang, Li Zhijian, Stefan Hajnoczi, Dave Gilbert,
	Vasiliy Tolstov, qemu-devel, Gonglei, Paolo Bonzini, Huangpeng,
	Guillaume Subiron

On 2016-03-07 13:14, Thomas Huth wrote:
> On 07.03.2016 13:06, Jan Kiszka wrote:
>> On 2016-03-07 12:09, Samuel Thibault wrote:
>>> Jason Wang, on Mon 07 Mar 2016 13:03:11 +0800, wrote:
>>>> Btw, do you want to be the maintainer of slirp? (Or maybe Tohmas want to
>>>> do this?)
>>>
>>> I already said I was fine with it, yes, and submitted a MAINTAINERS
>>> patch towards that, without any response.
>>
>> Sorry if I should have missed that, you would have my ack. Can you
>> resend or provide a pointer?
> 
> Patch is available here:
> 
> https://patchwork.ozlabs.org/patch/504661/
> 
> It has even been ack'd by Stefan at that point in time. Could somebody
> from the maintainers please pick this patch up? Jason (via net)? Paolo
> (via misc)? Jan (via slirp), if you can find some spare minutes?

My ack is there, so Samuel should simply send pulls to Peter directly
from now on, with the first one including this patch.

Jan

-- 
Siemens AG, Corporate Technology, CT RDA ITP SES-DE
Corporate Competence Center Embedded Linux

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [Qemu-devel] [PATCHv9 02/10] slirp: Adding ICMPv6 error sending
  2016-03-07  6:55   ` Jason Wang
@ 2016-03-07 13:34     ` Samuel Thibault
  0 siblings, 0 replies; 51+ messages in thread
From: Samuel Thibault @ 2016-03-07 13:34 UTC (permalink / raw)
  To: Jason Wang
  Cc: Thomas Huth, zhanghailiang, Li Zhijian, Stefan Hajnoczi,
	Dave Gilbert, Vasiliy Tolstov, qemu-devel, Yann Bordenave,
	Gonglei, Jan Kiszka, Huangpeng, Guillaume Subiron

Jason Wang, on Mon 07 Mar 2016 14:55:52 +0800, wrote:
> On 02/23/2016 03:28 AM, Samuel Thibault wrote:
> > From: Yann Bordenave <meow@meowstars.org>
> >
> > Disambiguation : icmp_error is renamed into icmp_send_error, since it
> > doesn't manage errors, but only sends ICMP Error messages.
> >
> > Adding icmp6_send_error to send ICMPv6 Error messages. This function is
> > simpler than the v4 version.
> > Adding some calls in various functions to send ICMP errors, when a
> > received packet is too big, or when its hop limit is 0.
> 
> Let's split this into two patches to avoid mixing renaming and new
> function introduction.

Ok, done so.

Samuel

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [Qemu-devel] [PATCHv9 0/10] slirp: Adding IPv6 support to Qemu -net user mode
  2016-03-07 12:00     ` Thomas Huth
@ 2016-03-07 13:37       ` Samuel Thibault
  0 siblings, 0 replies; 51+ messages in thread
From: Samuel Thibault @ 2016-03-07 13:37 UTC (permalink / raw)
  To: Thomas Huth
  Cc: zhanghailiang, Li Zhijian, Stefan Hajnoczi, Jason Wang,
	Dave Gilbert, Vasiliy Tolstov, qemu-devel, Gonglei, Jan Kiszka,
	Huangpeng, Guillaume Subiron

Thomas Huth, on Mon 07 Mar 2016 13:00:48 +0100, wrote:
> On 07.03.2016 12:19, Samuel Thibault wrote:
> > Jason Wang, on Mon 07 Mar 2016 14:48:16 +0800, wrote:
> >> - I expects a unit-test for this. You may want to have a look at the
> >> pxe-test in tests/, I think it could be extended to test ipv6 slirp somehow.
> > 
> > It doesn't seem so simple to me. In the case of PXE, you have a guest
> > implementation of PXE inside the BIOS. In the case of IPv6, I don't
> > think you have a guest implementation of IPv6 in the BIOS... So we'd
> > need to embed some guest that would do the IPv6 stuff. At best we can
> > make a qtest_start(), and that's about it.
> 
> Maybe we can use qemu-system-pppc64 for this ... the SLOF firmware has
> support for IPv6 already.

Ah, nice :)

> I can have a look at this if you like.

Yes.

I'm wondering whether that will be in time for the 2.6 window, however.
It seems more important to me to get the code more widely tested than
adding the unit-test.

Samuel

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [Qemu-devel] [PATCHv9 0/10] slirp: Adding IPv6 support to Qemu -net user mode
  2016-03-07 11:55   ` Samuel Thibault
@ 2016-03-07 15:37     ` Thomas Huth
  2016-03-07 16:49       ` Samuel Thibault
  2016-03-08  2:15     ` Jason Wang
  1 sibling, 1 reply; 51+ messages in thread
From: Thomas Huth @ 2016-03-07 15:37 UTC (permalink / raw)
  To: Samuel Thibault, Jason Wang
  Cc: zhanghailiang, Li Zhijian, Stefan Hajnoczi, Dave Gilbert,
	Vasiliy Tolstov, qemu-devel, Gonglei, Jan Kiszka, Huangpeng,
	Guillaume Subiron

On 07.03.2016 12:55, Samuel Thibault wrote:
> Jason Wang, on Mon 07 Mar 2016 14:48:16 +0800, wrote:
>> - the series does not build on w32:
>> In file included from ./slirp/slirp.h:126:0,
>>                  from stubs/slirp.c:3:
>> ./slirp/ip6.h:9:24: fatal error: netinet/in.h: No such file or directory
> 
> Is it the only issue?  Does it build if you add #ifndef _WIN32 around
> that include?

Is that "#include <netinet/in.h>" required in ip6.h at all? It also seems
to compile if I omit that include completely here...

Anyway, I just tried with my mingw32 cross-compiler, and once this is fixed,
compilation succeeds, but there are some warnings:

net/slirp.c: In function 'net_slirp_init':
net/slirp.c:249:5: warning: implicit declaration of function 'inet_pton' [-Wimplicit-function-declaration]
     if (!inet_pton(AF_INET6, vprefix6, &ip6_prefix)) {
     ^
slirp/ip6_icmp.c: In function 'icmp6_send_error':
slirp/ip6_icmp.c:84:5: warning: implicit declaration of function 'inet_ntop' [-Wimplicit-function-declaration]
     inet_ntop(AF_INET6, &rip->ip_dst, addrstr, INET6_ADDRSTRLEN);
     ^
qemu/slirp/ndp_table.c: In function 'ndp_table_add':
qemu/slirp/ndp_table.c:16:5: warning: implicit declaration of function 'inet_ntop' [-Wimplicit-function-declaration]
     inet_ntop(AF_INET6, &(ip_addr), addrstr, INET6_ADDRSTRLEN);

The warnings go away when I use this piece of code in the beginning of the affected files:

#ifdef _WIN32
#define _WIN32_WINNT _WIN32_WINNT_WIN6 
#include <ws2tcpip.h>
#endif

 Thomas

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [Qemu-devel] [PATCHv9 09/10] qapi-schema, qemu-options & slirp: Adding Qemu options for IPv6 addresses
  2016-03-07 11:41     ` Samuel Thibault
@ 2016-03-07 16:05       ` Eric Blake
  0 siblings, 0 replies; 51+ messages in thread
From: Eric Blake @ 2016-03-07 16:05 UTC (permalink / raw)
  To: Samuel Thibault, Jason Wang
  Cc: Thomas Huth, zhanghailiang, Li Zhijian, Stefan Hajnoczi,
	qemu-devel, Vasiliy Tolstov, Dave Gilbert, Yann Bordenave,
	Gonglei, Jan Kiszka, Huangpeng, Guillaume Subiron

[-- Attachment #1: Type: text/plain, Size: 753 bytes --]

On 03/07/2016 04:41 AM, Samuel Thibault wrote:
> Jason Wang, on Mon 07 Mar 2016 15:05:05 +0800, wrote:
>> Please do unnecessary changes like this since it will cause extra effort
>> for git blame and other things.
> 
> Ok. I just do hope that no other reviewer will come and say that we
> should fix the alignment of the parameters.

Alignment doesn't matter; in fact, most qapi .json files use
 'name': 'type

with a single space after : for every parameter, rather than trying to
align things.  It doesn't bother me either way (or I would have pointed
it out sooner), but reindenting is more churn than I would personally do.

-- 
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 604 bytes --]

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [Qemu-devel] [PATCHv9 0/10] slirp: Adding IPv6 support to Qemu -net user mode
  2016-03-07 15:37     ` Thomas Huth
@ 2016-03-07 16:49       ` Samuel Thibault
  0 siblings, 0 replies; 51+ messages in thread
From: Samuel Thibault @ 2016-03-07 16:49 UTC (permalink / raw)
  To: Thomas Huth
  Cc: zhanghailiang, Li Zhijian, Stefan Hajnoczi, Jason Wang,
	Dave Gilbert, Vasiliy Tolstov, qemu-devel, Gonglei, Jan Kiszka,
	Huangpeng, Guillaume Subiron

Hello,

Thomas Huth, on Mon 07 Mar 2016 16:37:59 +0100, wrote:
> Is that "#include <netinet/in.h>" required in ip6.h at all? It also seems
> to compile if I omit that include completely here...

Well, it makes sense to put it in ip6.h.  That said, since ip6.h is only
included through slirp.h which includes netinet/in.h appropriately, we
can indeed drop it from ip6.h

> Anyway, I just tried with my mingw32 cross-compiler, and once this is fixed,
> compilation succeeds, but there are some warnings:
> 
> net/slirp.c: In function 'net_slirp_init':
> net/slirp.c:249:5: warning: implicit declaration of function 'inet_pton' [-Wimplicit-function-declaration]
>      if (!inet_pton(AF_INET6, vprefix6, &ip6_prefix)) {
>      ^
> slirp/ip6_icmp.c: In function 'icmp6_send_error':
> slirp/ip6_icmp.c:84:5: warning: implicit declaration of function 'inet_ntop' [-Wimplicit-function-declaration]
>      inet_ntop(AF_INET6, &rip->ip_dst, addrstr, INET6_ADDRSTRLEN);
>      ^
> qemu/slirp/ndp_table.c: In function 'ndp_table_add':
> qemu/slirp/ndp_table.c:16:5: warning: implicit declaration of function 'inet_ntop' [-Wimplicit-function-declaration]
>      inet_ntop(AF_INET6, &(ip_addr), addrstr, INET6_ADDRSTRLEN);
> 
> The warnings go away when I use this piece of code in the beginning of the affected files:
> 
> #ifdef _WIN32
> #define _WIN32_WINNT _WIN32_WINNT_WIN6 
> #include <ws2tcpip.h>
> #endif

Eeeww, so windows only provides inet_pton since Vista?!  Ok, for now
I'll just disable using inet_ntop/pton when built with compatibility
before vista, i.e. notably

#if defined(_WIN32) && (_WIN32_WINNT < 0x0600)
hardcode fec0::
#endif

and refuse to configure the prefix, host and dns.

Samuel

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [Qemu-devel] [PATCHv9 0/10] slirp: Adding IPv6 support to Qemu -net user mode
  2016-03-07 11:09         ` Samuel Thibault
  2016-03-07 12:06           ` Jan Kiszka
@ 2016-03-08  1:37           ` Jason Wang
  1 sibling, 0 replies; 51+ messages in thread
From: Jason Wang @ 2016-03-08  1:37 UTC (permalink / raw)
  To: Samuel Thibault
  Cc: Thomas Huth, zhanghailiang, Li Zhijian, Stefan Hajnoczi,
	qemu-devel, Vasiliy Tolstov, Dave Gilbert, Gonglei, Jan Kiszka,
	Huangpeng, Guillaume Subiron



On 03/07/2016 07:09 PM, Samuel Thibault wrote:
> Jason Wang, on Mon 07 Mar 2016 13:03:11 +0800, wrote:
>> Btw, do you want to be the maintainer of slirp? (Or maybe Tohmas want to
>> do this?)
> I already said I was fine with it, yes, and submitted a MAINTAINERS
> patch towards that, without any response.
>
> Samuel
>

For some reason, I miss this. Will pick the patch.

Thanks

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [Qemu-devel] [PATCHv9 01/10] slirp: Adding IPv6, ICMPv6 Echo and NDP autoconfiguration
  2016-03-07 11:24     ` Samuel Thibault
@ 2016-03-08  1:39       ` Jason Wang
  0 siblings, 0 replies; 51+ messages in thread
From: Jason Wang @ 2016-03-08  1:39 UTC (permalink / raw)
  To: Samuel Thibault
  Cc: Thomas Huth, zhanghailiang, Li Zhijian, Stefan Hajnoczi,
	Dave Gilbert, Vasiliy Tolstov, qemu-devel, Gonglei, Jan Kiszka,
	Huangpeng, Guillaume Subiron



On 03/07/2016 07:24 PM, Samuel Thibault wrote:
> Jason Wang, on Mon 07 Mar 2016 14:53:54 +0800, wrote:
>>> +    switch (ip6->ip_nh) {
>>> +#if 0
>>> +    case IPPROTO_TCP:
>>> +        tcp_input(m, hlen, (struct socket *)NULL);
>>> +        break;
>>> +    case IPPROTO_UDP:
>>> +        udp_input(m, hlen);
>>> +        break;
>>> +#endif
>> This looks odd, why need this?
> To pave the way for the patches after that. We can drop that from this
> patch and move to the other ones if you will, I just believe it makes
> reading this one easier since it explains how tcp and udp will be
> plugged here.
>
> Samuel

This lead warnings in checkpatch, maybe it's better to use comment instead?

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [Qemu-devel] [PATCHv9 03/10] slirp: Adding IPv6 UDP support
  2016-03-07 11:36     ` Samuel Thibault
@ 2016-03-08  1:40       ` Jason Wang
  0 siblings, 0 replies; 51+ messages in thread
From: Jason Wang @ 2016-03-08  1:40 UTC (permalink / raw)
  To: Samuel Thibault
  Cc: Thomas Huth, zhanghailiang, Li Zhijian, Stefan Hajnoczi,
	Dave Gilbert, Vasiliy Tolstov, qemu-devel, Gonglei, Jan Kiszka,
	Huangpeng, Guillaume Subiron



On 03/07/2016 07:36 PM, Samuel Thibault wrote:
> Jason Wang, on Mon 07 Mar 2016 14:57:11 +0800, wrote:
>> Part of the codes looks duplicated with ipv4 version. Any chances to
>> merge them like tcp?
> The duplication is actually quite small: accessing the ip length
> is different, filling the address is different, etc.  So there are
> differences all along the code.  Is it really worth the factorization?
> It seems to me that it would actually *reduce* lisibility.
>
> Samuel
>

I see, so it's ok to leave this patch as is.

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [Qemu-devel] [PATCHv9 06/10] slirp: Reindent after refactoring
  2016-03-07 11:38     ` Samuel Thibault
@ 2016-03-08  1:43       ` Jason Wang
  0 siblings, 0 replies; 51+ messages in thread
From: Jason Wang @ 2016-03-08  1:43 UTC (permalink / raw)
  To: Samuel Thibault
  Cc: Thomas Huth, zhanghailiang, Li Zhijian, Stefan Hajnoczi,
	Dave Gilbert, Vasiliy Tolstov, qemu-devel, Gonglei, Jan Kiszka,
	Huangpeng, Guillaume Subiron



On 03/07/2016 07:38 PM, Samuel Thibault wrote:
> Jason Wang, on Mon 07 Mar 2016 15:02:53 +0800, wrote:
>> On 02/23/2016 03:28 AM, Samuel Thibault wrote:
>>> From: Guillaume Subiron <maethor@subiron.org>
>>>
>>> No code change.
>>>
>>> Signed-off-by: Guillaume Subiron <maethor@subiron.org>
>>> Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
>>> Reviewed-by: Thomas Huth <thuth@redhat.com>
>>> ---
>>>  slirp/tcp_input.c  | 92 +++++++++++++++++++++++++++---------------------------
>>>  slirp/tcp_output.c | 29 +++++++++--------
>>>  slirp/tcp_subr.c   | 50 ++++++++++++++---------------
>> How about other files in slirp/ ?
> What do you mean?  This patch is just meant to reindent the code after
> 'if's and 'case's have been added without reindentation to make it more
> readable.
>
> Do you mean reindenting the whole slirp?  That's quite another work...
>
> Samuel
>

I'm asking since I'm not sure partial reindenting is a the best choice
for us. The patch itself is ok.

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [Qemu-devel] [PATCHv9 0/10] slirp: Adding IPv6 support to Qemu -net user mode
  2016-03-07 11:55   ` Samuel Thibault
  2016-03-07 15:37     ` Thomas Huth
@ 2016-03-08  2:15     ` Jason Wang
  2016-03-08  9:12       ` Samuel Thibault
  1 sibling, 1 reply; 51+ messages in thread
From: Jason Wang @ 2016-03-08  2:15 UTC (permalink / raw)
  To: Samuel Thibault
  Cc: Thomas Huth, zhanghailiang, Li Zhijian, Stefan Hajnoczi,
	Dave Gilbert, Vasiliy Tolstov, qemu-devel, Gonglei, Jan Kiszka,
	Huangpeng, Guillaume Subiron



On 03/07/2016 07:55 PM, Samuel Thibault wrote:
> Jason Wang, on Mon 07 Mar 2016 14:48:16 +0800, wrote:
>> - the series does not build on w32:
>> In file included from ./slirp/slirp.h:126:0,
>>                  from stubs/slirp.c:3:
>> ./slirp/ip6.h:9:24: fatal error: netinet/in.h: No such file or directory
> Is it the only issue?  Does it build if you add #ifndef _WIN32 around
> that include?

Build works but get some warnings:


slirp/ip6_icmp.c: In function 'icmp6_send_error':
slirp/ip6_icmp.c:84:5: warning: implicit declaration of function
'inet_ntop' [-Wimplicit-function-declaration]
     inet_ntop(AF_INET6, &rip->ip_dst, addrstr, INET6_ADDRSTRLEN);
     ^
slirp/ip6_icmp.c:84:5: warning: nested extern declaration of 'inet_ntop'
[-Wnested-externs]

and

slirp/slirp.c: In function 'slirp_init':
slirp/slirp.c:226:5: warning: implicit declaration of function
'inet_pton' [-Wimplicit-function-declaration]
     inet_pton(AF_INET6, "fec0::0", &slirp->vprefix_addr6);
     ^
slirp/slirp.c:226:5: warning: nested extern declaration of 'inet_pton'
[-Wnested-externs]

(btw, you may refer http://wiki.qemu.org/Hosts/W32 to test this yourself).

>
> Samuel
>

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [Qemu-devel] [PATCHv9 0/10] slirp: Adding IPv6 support to Qemu -net user mode
  2016-03-07 11:19   ` Samuel Thibault
  2016-03-07 12:00     ` Thomas Huth
@ 2016-03-08  2:48     ` Jason Wang
  2016-03-08  8:53       ` Samuel Thibault
  1 sibling, 1 reply; 51+ messages in thread
From: Jason Wang @ 2016-03-08  2:48 UTC (permalink / raw)
  To: Samuel Thibault
  Cc: Thomas Huth, zhanghailiang, Li Zhijian, Stefan Hajnoczi,
	Dave Gilbert, Vasiliy Tolstov, qemu-devel, Gonglei, Jan Kiszka,
	Huangpeng, Guillaume Subiron



On 03/07/2016 07:19 PM, Samuel Thibault wrote:
> Jason Wang, on Mon 07 Mar 2016 14:48:16 +0800, wrote:
>> - Lots of checkpatch warnings, let's try to silent it.
> They are indentation issues, yes. They are already existing in slirp/
> . Whenever new code was added we sticked with the qemu style, but for
> patched code we prefered to stick to the existing indentation, since
> otherwise it'd mean reindenting it all to keep the functions readable at
> all. Do you what to see the whole slirp directory be reindented once for
> good before this gets applied? Personally I just don't care which way or
> the other.

Not only for indentation issue, e.g:

./scripts/checkpatch.pl
0001-slirp-Adding-IPv6-ICMPv6-Echo-and-NDP-autoconfigurat.patch
ERROR: return is not a function, parentheses are not required
#177: FILE: slirp/ip6.h:65:
+    return (a->s6_addr[prefix_len / 8] & ((1U << (8 - (prefix_len %
8))) - 1))

WARNING: line over 80 characters
#270: FILE: slirp/ip6_icmp.c:14:
+#define NDP_Interval g_rand_int_range(slirp->grand,
NDP_MinRtrAdvInterval, NDP_MaxRtrAdvInterval)

WARNING: if this code is redundant consider removing it
#870: FILE: slirp/ip6_input.c:52:
+#if 0

total: 1 errors, 2 warnings, 1121 lines checked

0001-slirp-Adding-IPv6-ICMPv6-Echo-and-NDP-autoconfigurat.patch has
style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.


>
>> - The patches do not apply to master cleanly.
> It did at the time I sent them...

Right, but not now, so please rebase.

>
>> - I expects a unit-test for this. You may want to have a look at the
>> pxe-test in tests/, I think it could be extended to test ipv6 slirp somehow.
> It doesn't seem so simple to me. In the case of PXE, you have a guest
> implementation of PXE inside the BIOS. In the case of IPv6, I don't
> think you have a guest implementation of IPv6 in the BIOS... So we'd
> need to embed some guest that would do the IPv6 stuff. At best we can
> make a qtest_start(), and that's about it.

Haven't think about this deeply, but at least from the source code, ipxe
did support ipv6. But I agree this could be done in the future.

>
> I'm awfully tired of all of this. This work has been done 3 years ago,
> has already seen 9 iterations. Had it not been something important to
> my eyes (being able to easily test ipv6), I would have abandoned a long
> time ago.

Sorry for this, I know how tired of this, and thanks a lot for not
giving up. I think the patch is pretty ready to be merged after one more
iteration.

>
> At the university of Bordeaux, we are planning to add a FOSS course with
> students participating to existing FOSS projects. I'm afraid we will
> just not be able to make them work on qemu at all.
>
> Samuel

I see, we still have time before hard freeze. So let's try to make it
for 2.6.

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [Qemu-devel] [PATCHv9 0/10] slirp: Adding IPv6 support to Qemu -net user mode
  2016-03-07 12:16               ` Jan Kiszka
@ 2016-03-08  2:50                 ` Jason Wang
  0 siblings, 0 replies; 51+ messages in thread
From: Jason Wang @ 2016-03-08  2:50 UTC (permalink / raw)
  To: Jan Kiszka, Thomas Huth, Samuel Thibault, Peter Maydell
  Cc: zhanghailiang, Li Zhijian, Stefan Hajnoczi, qemu-devel,
	Vasiliy Tolstov, Dave Gilbert, Gonglei, Paolo Bonzini, Huangpeng,
	Guillaume Subiron



On 03/07/2016 08:16 PM, Jan Kiszka wrote:
> On 2016-03-07 13:14, Thomas Huth wrote:
>> On 07.03.2016 13:06, Jan Kiszka wrote:
>>> On 2016-03-07 12:09, Samuel Thibault wrote:
>>>> Jason Wang, on Mon 07 Mar 2016 13:03:11 +0800, wrote:
>>>>> Btw, do you want to be the maintainer of slirp? (Or maybe Tohmas want to
>>>>> do this?)
>>>> I already said I was fine with it, yes, and submitted a MAINTAINERS
>>>> patch towards that, without any response.
>>> Sorry if I should have missed that, you would have my ack. Can you
>>> resend or provide a pointer?
>> Patch is available here:
>>
>> https://patchwork.ozlabs.org/patch/504661/
>>
>> It has even been ack'd by Stefan at that point in time. Could somebody
>> from the maintainers please pick this patch up? Jason (via net)? Paolo
>> (via misc)? Jan (via slirp), if you can find some spare minutes?
> My ack is there, so Samuel should simply send pulls to Peter directly
> from now on, with the first one including this patch.
>
> Jan
>

Plan to pick the patch, but this looks also fine with me.

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [Qemu-devel] [PATCHv9 0/10] slirp: Adding IPv6 support to Qemu -net user mode
  2016-03-08  2:48     ` Jason Wang
@ 2016-03-08  8:53       ` Samuel Thibault
  0 siblings, 0 replies; 51+ messages in thread
From: Samuel Thibault @ 2016-03-08  8:53 UTC (permalink / raw)
  To: Jason Wang
  Cc: Thomas Huth, zhanghailiang, Li Zhijian, Stefan Hajnoczi,
	Dave Gilbert, Vasiliy Tolstov, qemu-devel, Gonglei, Jan Kiszka,
	Huangpeng, Guillaume Subiron

Jason Wang, on Tue 08 Mar 2016 10:48:27 +0800, wrote:
> ./scripts/checkpatch.pl
> 0001-slirp-Adding-IPv6-ICMPv6-Echo-and-NDP-autoconfigurat.patch
> ERROR: return is not a function, parentheses are not required
> #177: FILE: slirp/ip6.h:65:
> +    return (a->s6_addr[prefix_len / 8] & ((1U << (8 - (prefix_len %
> 8))) - 1))

This is a false positive, the parentheses here are part of the
expression.

> WARNING: line over 80 characters
> #270: FILE: slirp/ip6_icmp.c:14:
> +#define NDP_Interval g_rand_int_range(slirp->grand,
> NDP_MinRtrAdvInterval, NDP_MaxRtrAdvInterval)

That was a real one yes, introduced when I was asked to use
g_rand_int_range, I have fixed it already.

> WARNING: if this code is redundant consider removing it
> #870: FILE: slirp/ip6_input.c:52:
> +#if 0

That's what we discuss in the other mail.  Yes, we can use comments.  It
just looks odd that we are talking about some code which goes away in a
subsequent patch :)

> >> - The patches do not apply to master cleanly.
> > It did at the time I sent them...
> 
> Right, but not now, so please rebase.

Sure... Already done so.

Samuel

^ permalink raw reply	[flat|nested] 51+ messages in thread

* Re: [Qemu-devel] [PATCHv9 0/10] slirp: Adding IPv6 support to Qemu -net user mode
  2016-03-08  2:15     ` Jason Wang
@ 2016-03-08  9:12       ` Samuel Thibault
  0 siblings, 0 replies; 51+ messages in thread
From: Samuel Thibault @ 2016-03-08  9:12 UTC (permalink / raw)
  To: Jason Wang
  Cc: Thomas Huth, zhanghailiang, Li Zhijian, Stefan Hajnoczi,
	Dave Gilbert, Vasiliy Tolstov, qemu-devel, Gonglei, Jan Kiszka,
	Huangpeng, Guillaume Subiron

Jason Wang, on Tue 08 Mar 2016 10:15:57 +0800, wrote:
> Build works but get some warnings:
> 
> 
> slirp/ip6_icmp.c: In function 'icmp6_send_error':
> slirp/ip6_icmp.c:84:5: warning: implicit declaration of function
> 'inet_ntop' [-Wimplicit-function-declaration]
>      inet_ntop(AF_INET6, &rip->ip_dst, addrstr, INET6_ADDRSTRLEN);
>      ^
> slirp/ip6_icmp.c:84:5: warning: nested extern declaration of 'inet_ntop'
> [-Wnested-externs]
> 
> and
> 
> slirp/slirp.c: In function 'slirp_init':
> slirp/slirp.c:226:5: warning: implicit declaration of function
> 'inet_pton' [-Wimplicit-function-declaration]
>      inet_pton(AF_INET6, "fec0::0", &slirp->vprefix_addr6);
>      ^
> slirp/slirp.c:226:5: warning: nested extern declaration of 'inet_pton'
> [-Wnested-externs]

Thomas reported them in another mail, yes.  I have changed that into not
using inet_pton/ntop when built with windows compatibility before Vista.

> (btw, you may refer http://wiki.qemu.org/Hosts/W32 to test this yourself).

I've tried it yesterday, yes, but now qemu needs glib & such, so it'd
need cross-building it...

Samuel

^ permalink raw reply	[flat|nested] 51+ messages in thread

end of thread, other threads:[~2016-03-08  9:13 UTC | newest]

Thread overview: 51+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-02-22 19:28 [Qemu-devel] [PATCHv9 0/10] slirp: Adding IPv6 support to Qemu -net user mode Samuel Thibault
2016-02-22 19:28 ` [Qemu-devel] [PATCHv9 01/10] slirp: Adding IPv6, ICMPv6 Echo and NDP autoconfiguration Samuel Thibault
2016-03-07  6:53   ` Jason Wang
2016-03-07 11:24     ` Samuel Thibault
2016-03-08  1:39       ` Jason Wang
2016-02-22 19:28 ` [Qemu-devel] [PATCHv9 02/10] slirp: Adding ICMPv6 error sending Samuel Thibault
2016-03-07  6:55   ` Jason Wang
2016-03-07 13:34     ` Samuel Thibault
2016-02-22 19:28 ` [Qemu-devel] [PATCHv9 03/10] slirp: Adding IPv6 UDP support Samuel Thibault
2016-03-07  6:57   ` Jason Wang
2016-03-07 11:36     ` Samuel Thibault
2016-03-08  1:40       ` Jason Wang
2016-02-22 19:28 ` [Qemu-devel] [PATCHv9 04/10] slirp: Factorizing tcpiphdr structure with an union Samuel Thibault
2016-02-23  8:07   ` Thomas Huth
2016-02-22 19:28 ` [Qemu-devel] [PATCHv9 05/10] slirp: Generalizing and neutralizing various TCP functions before adding IPv6 stuff Samuel Thibault
2016-02-22 19:28 ` [Qemu-devel] [PATCHv9 06/10] slirp: Reindent after refactoring Samuel Thibault
2016-03-07  7:02   ` Jason Wang
2016-03-07 11:38     ` Samuel Thibault
2016-03-08  1:43       ` Jason Wang
2016-02-22 19:28 ` [Qemu-devel] [PATCHv9 07/10] slirp: Handle IPv6 in TCP functions Samuel Thibault
2016-02-22 19:28 ` [Qemu-devel] [PATCHv9 08/10] slirp: Adding IPv6 address for DNS relay Samuel Thibault
2016-02-23  8:12   ` Thomas Huth
2016-02-22 19:28 ` [Qemu-devel] [PATCHv9 09/10] qapi-schema, qemu-options & slirp: Adding Qemu options for IPv6 addresses Samuel Thibault
2016-02-23  8:27   ` Thomas Huth
2016-03-07  7:05   ` Jason Wang
2016-03-07 11:39     ` Samuel Thibault
2016-03-07 11:41     ` Samuel Thibault
2016-03-07 16:05       ` Eric Blake
2016-02-22 19:28 ` [Qemu-devel] [PATCHv9 10/10] slirp: Add IPv6 support to the TFTP code Samuel Thibault
2016-03-04  8:41 ` [Qemu-devel] [PATCHv9 0/10] slirp: Adding IPv6 support to Qemu -net user mode Thomas Huth
2016-03-04 15:50   ` Jan Kiszka
2016-03-06 16:59     ` Samuel Thibault
2016-03-07  5:03       ` Jason Wang
2016-03-07 11:09         ` Samuel Thibault
2016-03-07 12:06           ` Jan Kiszka
2016-03-07 12:11             ` Samuel Thibault
2016-03-07 12:14             ` Thomas Huth
2016-03-07 12:16               ` Jan Kiszka
2016-03-08  2:50                 ` Jason Wang
2016-03-08  1:37           ` Jason Wang
2016-03-07  6:48 ` Jason Wang
2016-03-07 11:19   ` Samuel Thibault
2016-03-07 12:00     ` Thomas Huth
2016-03-07 13:37       ` Samuel Thibault
2016-03-08  2:48     ` Jason Wang
2016-03-08  8:53       ` Samuel Thibault
2016-03-07 11:55   ` Samuel Thibault
2016-03-07 15:37     ` Thomas Huth
2016-03-07 16:49       ` Samuel Thibault
2016-03-08  2:15     ` Jason Wang
2016-03-08  9:12       ` Samuel Thibault

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).