Some work on the libslirp networking support.

- Added capability to turn on IPv6 support with slirp.conf option (using default
  QEMU settings for now / non-Windows platforms only).
- Added some basic timer code required by IPv6 based on example code.
This commit is contained in:
Volker Ruppert 2024-04-13 10:18:38 +02:00
parent 0ff2905998
commit 155fc74d30
2 changed files with 90 additions and 4 deletions

View File

@ -17,7 +17,8 @@
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
//
// eth_slirp.cc - Bochs port of Qemu's slirp implementation
// eth_slirp.cc - Bochs port of Qemu's slirp implementation (plus libslirp support)
// Portion of this software comes with the following license: BSD-3-Clause
#define BX_PLUGGABLE
@ -71,7 +72,10 @@ public:
virtual ~bx_slirp_pktmover_c();
void sendpkt(void *buf, unsigned io_len);
void receive(void *pkt, unsigned pkt_len);
int can_receive(void);
int can_receive(void);
#if BX_HAVE_LIBSLIRP
void slirp_msg(const char *msg);
#endif
private:
Slirp *slirp;
unsigned netdev_speed;
@ -116,7 +120,10 @@ static slirp_ssize_t send_packet(const void *buf, size_t len, void *opaque);
static void guest_error(const char *msg, void *opaque)
{
fprintf(stderr, "guest_error\n");
char errmsg[512];
sprintf(errmsg, "guest error: %s", msg);
((bx_slirp_pktmover_c*)opaque)->slirp_msg(errmsg);
}
static int64_t clock_get_ns(void *opaque)
@ -124,6 +131,59 @@ static int64_t clock_get_ns(void *opaque)
return bx_pc_system.time_usec() * 1000;
}
struct timer {
SlirpTimerId id;
void *cb_opaque;
int64_t expire;
struct timer *next;
};
static struct timer *timer_queue;
static void *timer_new_opaque(SlirpTimerId id, void *cb_opaque, void *opaque)
{
((bx_slirp_pktmover_c*)opaque)->slirp_msg("timer_new_opaque()");
struct timer *new_timer = new timer;
new_timer->id = id;
new_timer->cb_opaque = cb_opaque;
new_timer->next = NULL;
return new_timer;
}
static void timer_free(void *_timer, void *opaque)
{
((bx_slirp_pktmover_c*)opaque)->slirp_msg("timer_free()");
struct timer *timer1 = (timer*)_timer;
struct timer **t;
for (t = &timer_queue; *t != NULL; *t = (*t)->next) {
if (*t == timer1) {
/* Not expired yet, drop it */
*t = timer1->next;
break;
}
}
delete [] timer1;
}
static void timer_mod(void *_timer, int64_t expire_time, void *opaque)
{
((bx_slirp_pktmover_c*)opaque)->slirp_msg("timer_mod()");
struct timer *timer1 = (timer*)_timer;
struct timer **t;
timer1->expire = expire_time * 1000 * 1000;
for (t = &timer_queue; *t != NULL; *t = (*t)->next) {
if (expire_time < (*t)->expire)
break;
}
timer1->next = *t;
*t = timer1;
}
static int npoll;
static void register_poll_fd(int fd, void *opaque)
@ -145,9 +205,12 @@ static struct SlirpCb callbacks = {
.send_packet = send_packet,
.guest_error = guest_error,
.clock_get_ns = clock_get_ns,
.timer_free = timer_free,
.timer_mod = timer_mod,
.register_poll_fd = register_poll_fd,
.unregister_poll_fd = unregister_poll_fd,
.notify = notify,
.timer_new_opaque = timer_new_opaque,
};
#endif
@ -217,6 +280,17 @@ bx_slirp_pktmover_c::bx_slirp_pktmover_c(const char *netif,
if (!parse_slirp_conf(script)) {
BX_ERROR(("reading slirp config failed"));
}
#if BX_HAVE_LIBSLIRP && !defined(_WIN32)
if (config.in6_enabled) {
BX_INFO(("IPv6 enabled (using default QEMU settings)"));
inet_pton(AF_INET6, "fec0::", &config.vprefix_addr6);
config.vprefix_len = 64;
config.vhost6 = config.vprefix_addr6;
config.vhost6.s6_addr[15] |= 2;
config.vnameserver6 = config.vprefix_addr6;
config.vnameserver6.s6_addr[15] |= 3;
}
#endif
}
#if BX_HAVE_LIBSLIRP
slirp = slirp_new(&config, &callbacks, this);
@ -428,6 +502,10 @@ bool bx_slirp_pktmover_c::parse_slirp_conf(const char *conf)
} else {
BX_ERROR(("slirp: wrong format for 'pktlog'"));
}
#if BX_HAVE_LIBSLIRP && !defined(_WIN32)
} else if (!stricmp(param, "ipv6_enabled")) {
config.in6_enabled = (atoi(val) != 0);
#endif
} else {
BX_ERROR(("slirp: unknown option '%s'", line));
}
@ -539,7 +617,12 @@ void bx_slirp_pktmover_c::receive(void *pkt, unsigned pkt_len)
}
#if BX_HAVE_LIBSLIRP
static slirp_ssize_t send_packet(const void *buf, size_t len, void *opaque)
void bx_slirp_pktmover_c::slirp_msg(const char *msg)
{
BX_INFO(("%s", msg));
}
static ssize_t send_packet(const void *buf, size_t len, void *opaque)
{
bx_slirp_pktmover_c *class_ptr = (bx_slirp_pktmover_c *)opaque;
class_ptr->receive((void*)buf, len);

View File

@ -37,5 +37,8 @@
# Host forwarding example (access guest SSH server from host port 12345)
# hostfwd = tcp::12345-:22
# Enable IPv6 support (libslirp only / using default Qemu setup)
# ipv6_enabled = 1
# Enable packet logging in text format (similar to vnet)
# pktlog = slirp-pktlog.txt