Commit c20709aa32045c79e21905c4c009aae53d008af5
1 parent
92cb7d54
initial user mode network support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@730 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
3 changed files
with
266 additions
and
84 deletions
configure
| ... | ... | @@ -71,6 +71,7 @@ bigendian="no" |
| 71 | 71 | mingw32="no" |
| 72 | 72 | EXESUF="" |
| 73 | 73 | gdbstub="yes" |
| 74 | +slirp="no" | |
| 74 | 75 | |
| 75 | 76 | # OS specific |
| 76 | 77 | targetos=`uname -s` |
| ... | ... | @@ -124,6 +125,8 @@ for opt do |
| 124 | 125 | ;; |
| 125 | 126 | --enable-mingw32) mingw32="yes" ; cross_prefix="i386-mingw32-" |
| 126 | 127 | ;; |
| 128 | + --enable-slirp) slirp="yes" | |
| 129 | + ;; | |
| 127 | 130 | esac |
| 128 | 131 | done |
| 129 | 132 | |
| ... | ... | @@ -378,6 +381,10 @@ if test "$sdl" = "yes" ; then |
| 378 | 381 | fi |
| 379 | 382 | echo "" >> $config_mak |
| 380 | 383 | fi |
| 384 | +if test "$slirp" = "yes" ; then | |
| 385 | + echo "CONFIG_SLIRP=yes" >> $config_mak | |
| 386 | + echo "#define CONFIG_SLIRP 1" >> $config_h | |
| 387 | +fi | |
| 381 | 388 | echo -n "VERSION=" >>$config_mak |
| 382 | 389 | head $source_path/VERSION >>$config_mak |
| 383 | 390 | echo "" >>$config_mak | ... | ... |
vl.c
| ... | ... | @@ -45,6 +45,10 @@ |
| 45 | 45 | #include <linux/if_tun.h> |
| 46 | 46 | #endif |
| 47 | 47 | |
| 48 | +#if defined(CONFIG_SLIRP) | |
| 49 | +#include "libslirp.h" | |
| 50 | +#endif | |
| 51 | + | |
| 48 | 52 | #ifdef _WIN32 |
| 49 | 53 | #include <sys/timeb.h> |
| 50 | 54 | #include <windows.h> |
| ... | ... | @@ -750,20 +754,121 @@ int serial_open_device(void) |
| 750 | 754 | #endif |
| 751 | 755 | |
| 752 | 756 | /***********************************************************/ |
| 753 | -/* Linux network device redirector */ | |
| 757 | +/* Linux network device redirectors */ | |
| 754 | 758 | |
| 755 | -#ifdef _WIN32 | |
| 759 | +void hex_dump(FILE *f, const uint8_t *buf, int size) | |
| 760 | +{ | |
| 761 | + int len, i, j, c; | |
| 762 | + | |
| 763 | + for(i=0;i<size;i+=16) { | |
| 764 | + len = size - i; | |
| 765 | + if (len > 16) | |
| 766 | + len = 16; | |
| 767 | + fprintf(f, "%08x ", i); | |
| 768 | + for(j=0;j<16;j++) { | |
| 769 | + if (j < len) | |
| 770 | + fprintf(f, " %02x", buf[i+j]); | |
| 771 | + else | |
| 772 | + fprintf(f, " "); | |
| 773 | + } | |
| 774 | + fprintf(f, " "); | |
| 775 | + for(j=0;j<len;j++) { | |
| 776 | + c = buf[i+j]; | |
| 777 | + if (c < ' ' || c > '~') | |
| 778 | + c = '.'; | |
| 779 | + fprintf(f, "%c", c); | |
| 780 | + } | |
| 781 | + fprintf(f, "\n"); | |
| 782 | + } | |
| 783 | +} | |
| 784 | + | |
| 785 | +void qemu_send_packet(NetDriverState *nd, const uint8_t *buf, int size) | |
| 786 | +{ | |
| 787 | + nd->send_packet(nd, buf, size); | |
| 788 | +} | |
| 756 | 789 | |
| 757 | -static int net_init(void) | |
| 790 | +void qemu_add_read_packet(NetDriverState *nd, IOCanRWHandler *fd_can_read, | |
| 791 | + IOReadHandler *fd_read, void *opaque) | |
| 758 | 792 | { |
| 793 | + nd->add_read_packet(nd, fd_can_read, fd_read, opaque); | |
| 794 | +} | |
| 795 | + | |
| 796 | +/* dummy network adapter */ | |
| 797 | + | |
| 798 | +static void dummy_send_packet(NetDriverState *nd, const uint8_t *buf, int size) | |
| 799 | +{ | |
| 800 | +} | |
| 801 | + | |
| 802 | +static void dummy_add_read_packet(NetDriverState *nd, | |
| 803 | + IOCanRWHandler *fd_can_read, | |
| 804 | + IOReadHandler *fd_read, void *opaque) | |
| 805 | +{ | |
| 806 | +} | |
| 807 | + | |
| 808 | +static int net_dummy_init(NetDriverState *nd) | |
| 809 | +{ | |
| 810 | + nd->send_packet = dummy_send_packet; | |
| 811 | + nd->add_read_packet = dummy_add_read_packet; | |
| 812 | + pstrcpy(nd->ifname, sizeof(nd->ifname), "dummy"); | |
| 759 | 813 | return 0; |
| 760 | 814 | } |
| 761 | 815 | |
| 762 | -void net_send_packet(NetDriverState *nd, const uint8_t *buf, int size) | |
| 816 | +#if defined(CONFIG_SLIRP) | |
| 817 | + | |
| 818 | +/* slirp network adapter */ | |
| 819 | + | |
| 820 | +static void *slirp_fd_opaque; | |
| 821 | +static IOCanRWHandler *slirp_fd_can_read; | |
| 822 | +static IOReadHandler *slirp_fd_read; | |
| 823 | +static int slirp_inited; | |
| 824 | + | |
| 825 | +int slirp_can_output(void) | |
| 826 | +{ | |
| 827 | + return slirp_fd_can_read(slirp_fd_opaque); | |
| 828 | +} | |
| 829 | + | |
| 830 | +void slirp_output(const uint8_t *pkt, int pkt_len) | |
| 763 | 831 | { |
| 832 | +#if 0 | |
| 833 | + printf("output:\n"); | |
| 834 | + hex_dump(stdout, pkt, pkt_len); | |
| 835 | +#endif | |
| 836 | + slirp_fd_read(slirp_fd_opaque, pkt, pkt_len); | |
| 764 | 837 | } |
| 765 | 838 | |
| 766 | -#else | |
| 839 | +static void slirp_send_packet(NetDriverState *nd, const uint8_t *buf, int size) | |
| 840 | +{ | |
| 841 | +#if 0 | |
| 842 | + printf("input:\n"); | |
| 843 | + hex_dump(stdout, buf, size); | |
| 844 | +#endif | |
| 845 | + slirp_input(buf, size); | |
| 846 | +} | |
| 847 | + | |
| 848 | +static void slirp_add_read_packet(NetDriverState *nd, | |
| 849 | + IOCanRWHandler *fd_can_read, | |
| 850 | + IOReadHandler *fd_read, void *opaque) | |
| 851 | +{ | |
| 852 | + slirp_fd_opaque = opaque; | |
| 853 | + slirp_fd_can_read = fd_can_read; | |
| 854 | + slirp_fd_read = fd_read; | |
| 855 | +} | |
| 856 | + | |
| 857 | +static int net_slirp_init(NetDriverState *nd) | |
| 858 | +{ | |
| 859 | + if (!slirp_inited) { | |
| 860 | + slirp_inited = 1; | |
| 861 | + slirp_init(); | |
| 862 | + } | |
| 863 | + nd->send_packet = slirp_send_packet; | |
| 864 | + nd->add_read_packet = slirp_add_read_packet; | |
| 865 | + pstrcpy(nd->ifname, sizeof(nd->ifname), "slirp"); | |
| 866 | + return 0; | |
| 867 | +} | |
| 868 | + | |
| 869 | +#endif /* CONFIG_SLIRP */ | |
| 870 | + | |
| 871 | +#if !defined(_WIN32) | |
| 767 | 872 | |
| 768 | 873 | static int tun_open(char *ifname, int ifname_size) |
| 769 | 874 | { |
| ... | ... | @@ -790,60 +895,61 @@ static int tun_open(char *ifname, int ifname_size) |
| 790 | 895 | return fd; |
| 791 | 896 | } |
| 792 | 897 | |
| 793 | -static int net_init(void) | |
| 898 | +static void tun_send_packet(NetDriverState *nd, const uint8_t *buf, int size) | |
| 899 | +{ | |
| 900 | + write(nd->fd, buf, size); | |
| 901 | +} | |
| 902 | + | |
| 903 | +static void tun_add_read_packet(NetDriverState *nd, | |
| 904 | + IOCanRWHandler *fd_can_read, | |
| 905 | + IOReadHandler *fd_read, void *opaque) | |
| 794 | 906 | { |
| 795 | - int pid, status, launch_script, i; | |
| 796 | - NetDriverState *nd; | |
| 797 | - char *args[MAX_NICS + 2]; | |
| 907 | + qemu_add_fd_read_handler(nd->fd, fd_can_read, fd_read, opaque); | |
| 908 | +} | |
| 909 | + | |
| 910 | +static int net_tun_init(NetDriverState *nd) | |
| 911 | +{ | |
| 912 | + int pid, status; | |
| 913 | + char *args[3]; | |
| 798 | 914 | char **parg; |
| 799 | 915 | |
| 800 | - launch_script = 0; | |
| 801 | - for(i = 0; i < nb_nics; i++) { | |
| 802 | - nd = &nd_table[i]; | |
| 803 | - if (nd->fd < 0) { | |
| 804 | - nd->fd = tun_open(nd->ifname, sizeof(nd->ifname)); | |
| 805 | - if (nd->fd >= 0) | |
| 806 | - launch_script = 1; | |
| 807 | - } | |
| 808 | - } | |
| 916 | + nd->fd = tun_open(nd->ifname, sizeof(nd->ifname)); | |
| 917 | + if (nd->fd < 0) | |
| 918 | + return -1; | |
| 809 | 919 | |
| 810 | - if (launch_script) { | |
| 811 | - /* try to launch network init script */ | |
| 812 | - pid = fork(); | |
| 813 | - if (pid >= 0) { | |
| 814 | - if (pid == 0) { | |
| 815 | - parg = args; | |
| 816 | - *parg++ = network_script; | |
| 817 | - for(i = 0; i < nb_nics; i++) { | |
| 818 | - nd = &nd_table[i]; | |
| 819 | - if (nd->fd >= 0) { | |
| 820 | - *parg++ = nd->ifname; | |
| 821 | - } | |
| 822 | - } | |
| 823 | - *parg++ = NULL; | |
| 824 | - execv(network_script, args); | |
| 825 | - exit(1); | |
| 826 | - } | |
| 827 | - while (waitpid(pid, &status, 0) != pid); | |
| 828 | - if (!WIFEXITED(status) || | |
| 829 | - WEXITSTATUS(status) != 0) { | |
| 830 | - fprintf(stderr, "%s: could not launch network script\n", | |
| 831 | - network_script); | |
| 832 | - } | |
| 920 | + /* try to launch network init script */ | |
| 921 | + pid = fork(); | |
| 922 | + if (pid >= 0) { | |
| 923 | + if (pid == 0) { | |
| 924 | + parg = args; | |
| 925 | + *parg++ = network_script; | |
| 926 | + *parg++ = nd->ifname; | |
| 927 | + *parg++ = NULL; | |
| 928 | + execv(network_script, args); | |
| 929 | + exit(1); | |
| 930 | + } | |
| 931 | + while (waitpid(pid, &status, 0) != pid); | |
| 932 | + if (!WIFEXITED(status) || | |
| 933 | + WEXITSTATUS(status) != 0) { | |
| 934 | + fprintf(stderr, "%s: could not launch network script\n", | |
| 935 | + network_script); | |
| 833 | 936 | } |
| 834 | 937 | } |
| 938 | + nd->send_packet = tun_send_packet; | |
| 939 | + nd->add_read_packet = tun_add_read_packet; | |
| 835 | 940 | return 0; |
| 836 | 941 | } |
| 837 | 942 | |
| 838 | -void net_send_packet(NetDriverState *nd, const uint8_t *buf, int size) | |
| 943 | +static int net_fd_init(NetDriverState *nd, int fd) | |
| 839 | 944 | { |
| 840 | -#ifdef DEBUG_NE2000 | |
| 841 | - printf("NE2000: sending packet size=%d\n", size); | |
| 842 | -#endif | |
| 843 | - write(nd->fd, buf, size); | |
| 945 | + nd->fd = fd; | |
| 946 | + nd->send_packet = tun_send_packet; | |
| 947 | + nd->add_read_packet = tun_add_read_packet; | |
| 948 | + pstrcpy(nd->ifname, sizeof(nd->ifname), "tunfd"); | |
| 949 | + return 0; | |
| 844 | 950 | } |
| 845 | 951 | |
| 846 | -#endif | |
| 952 | +#endif /* !_WIN32 */ | |
| 847 | 953 | |
| 848 | 954 | /***********************************************************/ |
| 849 | 955 | /* dumb display */ |
| ... | ... | @@ -1597,6 +1703,28 @@ int main_loop(void) |
| 1597 | 1703 | } |
| 1598 | 1704 | } |
| 1599 | 1705 | } |
| 1706 | + | |
| 1707 | +#if defined(CONFIG_SLIRP) | |
| 1708 | + /* XXX: merge with poll() */ | |
| 1709 | + if (slirp_inited) { | |
| 1710 | + fd_set rfds, wfds, xfds; | |
| 1711 | + int nfds; | |
| 1712 | + struct timeval tv; | |
| 1713 | + | |
| 1714 | + nfds = -1; | |
| 1715 | + FD_ZERO(&rfds); | |
| 1716 | + FD_ZERO(&wfds); | |
| 1717 | + FD_ZERO(&xfds); | |
| 1718 | + slirp_select_fill(&nfds, &rfds, &wfds, &xfds); | |
| 1719 | + tv.tv_sec = 0; | |
| 1720 | + tv.tv_usec = 0; | |
| 1721 | + ret = select(nfds + 1, &rfds, &wfds, &xfds, &tv); | |
| 1722 | + if (ret >= 0) { | |
| 1723 | + slirp_select_poll(&rfds, &wfds, &xfds); | |
| 1724 | + } | |
| 1725 | + } | |
| 1726 | +#endif | |
| 1727 | + | |
| 1600 | 1728 | #endif |
| 1601 | 1729 | |
| 1602 | 1730 | if (vm_running) { |
| ... | ... | @@ -1636,10 +1764,14 @@ void help(void) |
| 1636 | 1764 | "-nographic disable graphical output and redirect serial I/Os to console\n" |
| 1637 | 1765 | "\n" |
| 1638 | 1766 | "Network options:\n" |
| 1639 | - "-n script set network init script [default=%s]\n" | |
| 1640 | - "-nics n simulate 'n' network interfaces [default=1]\n" | |
| 1767 | + "-nics n simulate 'n' network cards [default=1]\n" | |
| 1641 | 1768 | "-macaddr addr set the mac address of the first interface\n" |
| 1642 | - "-tun-fd fd0[,...] use these fds as already opened tap/tun interfaces\n" | |
| 1769 | + "-n script set tap/tun network init script [default=%s]\n" | |
| 1770 | + "-tun-fd fd use this fd as already opened tap/tun interface\n" | |
| 1771 | +#ifdef CONFIG_SLIRP | |
| 1772 | + "-user-net use user mode network stack [default if no tap/tun script]\n" | |
| 1773 | +#endif | |
| 1774 | + "-dummy-net use dummy network stack\n" | |
| 1643 | 1775 | "\n" |
| 1644 | 1776 | "Linux boot specific:\n" |
| 1645 | 1777 | "-kernel bzImage use 'bzImage' as kernel image\n" |
| ... | ... | @@ -1695,6 +1827,8 @@ struct option long_options[] = { |
| 1695 | 1827 | { "no-code-copy", 0, NULL, 0 }, |
| 1696 | 1828 | { "nics", 1, NULL, 0 }, |
| 1697 | 1829 | { "macaddr", 1, NULL, 0 }, |
| 1830 | + { "user-net", 1, NULL, 0 }, | |
| 1831 | + { "dummy-net", 1, NULL, 0 }, | |
| 1698 | 1832 | { NULL, 0, NULL, 0 }, |
| 1699 | 1833 | }; |
| 1700 | 1834 | |
| ... | ... | @@ -1707,6 +1841,10 @@ static uint8_t *signal_stack; |
| 1707 | 1841 | |
| 1708 | 1842 | #endif |
| 1709 | 1843 | |
| 1844 | +#define NET_IF_TUN 0 | |
| 1845 | +#define NET_IF_USER 1 | |
| 1846 | +#define NET_IF_DUMMY 2 | |
| 1847 | + | |
| 1710 | 1848 | int main(int argc, char **argv) |
| 1711 | 1849 | { |
| 1712 | 1850 | #ifdef CONFIG_GDBSTUB |
| ... | ... | @@ -1722,7 +1860,8 @@ int main(int argc, char **argv) |
| 1722 | 1860 | int cyls, heads, secs; |
| 1723 | 1861 | int start_emulation = 1; |
| 1724 | 1862 | uint8_t macaddr[6]; |
| 1725 | - | |
| 1863 | + int net_if_type, nb_tun_fds, tun_fds[MAX_NICS]; | |
| 1864 | + | |
| 1726 | 1865 | #if !defined(CONFIG_SOFTMMU) |
| 1727 | 1866 | /* we never want that malloc() uses mmap() */ |
| 1728 | 1867 | mallopt(M_MMAP_THRESHOLD, 4096 * 1024); |
| ... | ... | @@ -1746,6 +1885,8 @@ int main(int argc, char **argv) |
| 1746 | 1885 | has_cdrom = 1; |
| 1747 | 1886 | cyls = heads = secs = 0; |
| 1748 | 1887 | |
| 1888 | + nb_tun_fds = 0; | |
| 1889 | + net_if_type = -1; | |
| 1749 | 1890 | nb_nics = 1; |
| 1750 | 1891 | /* default mac address of the first network interface */ |
| 1751 | 1892 | macaddr[0] = 0x52; |
| ... | ... | @@ -1754,10 +1895,8 @@ int main(int argc, char **argv) |
| 1754 | 1895 | macaddr[3] = 0x12; |
| 1755 | 1896 | macaddr[4] = 0x34; |
| 1756 | 1897 | macaddr[5] = 0x56; |
| 1757 | - | |
| 1758 | - for(i = 0; i < MAX_NICS; i++) | |
| 1759 | - nd_table[i].fd = -1; | |
| 1760 | - | |
| 1898 | + | |
| 1899 | + | |
| 1761 | 1900 | for(;;) { |
| 1762 | 1901 | c = getopt_long_only(argc, argv, "hm:d:n:sp:L:S", long_options, &long_index); |
| 1763 | 1902 | if (c == -1) |
| ... | ... | @@ -1809,23 +1948,13 @@ int main(int argc, char **argv) |
| 1809 | 1948 | { |
| 1810 | 1949 | const char *p; |
| 1811 | 1950 | int fd; |
| 1812 | - p = optarg; | |
| 1813 | - nb_nics = 0; | |
| 1814 | - for(;;) { | |
| 1815 | - fd = strtol(p, (char **)&p, 0); | |
| 1816 | - nd_table[nb_nics].fd = fd; | |
| 1817 | - snprintf(nd_table[nb_nics].ifname, | |
| 1818 | - sizeof(nd_table[nb_nics].ifname), | |
| 1819 | - "fd%d", nb_nics); | |
| 1820 | - nb_nics++; | |
| 1821 | - if (*p == ',') { | |
| 1822 | - p++; | |
| 1823 | - } else if (*p != '\0') { | |
| 1824 | - fprintf(stderr, "qemu: invalid fd for network interface %d\n", nb_nics); | |
| 1951 | + if (nb_tun_fds < MAX_NICS) { | |
| 1952 | + fd = strtol(optarg, (char **)&p, 0); | |
| 1953 | + if (*p != '\0') { | |
| 1954 | + fprintf(stderr, "qemu: invalid fd for network interface %d\n", nb_tun_fds); | |
| 1825 | 1955 | exit(1); |
| 1826 | - } else { | |
| 1827 | - break; | |
| 1828 | 1956 | } |
| 1957 | + tun_fds[nb_tun_fds++] = fd; | |
| 1829 | 1958 | } |
| 1830 | 1959 | } |
| 1831 | 1960 | break; |
| ... | ... | @@ -1885,6 +2014,12 @@ int main(int argc, char **argv) |
| 1885 | 2014 | } |
| 1886 | 2015 | } |
| 1887 | 2016 | break; |
| 2017 | + case 18: | |
| 2018 | + net_if_type = NET_IF_USER; | |
| 2019 | + break; | |
| 2020 | + case 19: | |
| 2021 | + net_if_type = NET_IF_DUMMY; | |
| 2022 | + break; | |
| 1888 | 2023 | } |
| 1889 | 2024 | break; |
| 1890 | 2025 | case 'h': |
| ... | ... | @@ -1965,8 +2100,18 @@ int main(int argc, char **argv) |
| 1965 | 2100 | #endif |
| 1966 | 2101 | |
| 1967 | 2102 | /* init host network redirectors */ |
| 1968 | - for(i = 0; i < MAX_NICS; i++) { | |
| 2103 | + if (net_if_type == -1) { | |
| 2104 | + net_if_type = NET_IF_TUN; | |
| 2105 | +#if defined(CONFIG_SLIRP) | |
| 2106 | + if (access(network_script, R_OK) < 0) { | |
| 2107 | + net_if_type = NET_IF_USER; | |
| 2108 | + } | |
| 2109 | +#endif | |
| 2110 | + } | |
| 2111 | + | |
| 2112 | + for(i = 0; i < nb_nics; i++) { | |
| 1969 | 2113 | NetDriverState *nd = &nd_table[i]; |
| 2114 | + nd->index = i; | |
| 1970 | 2115 | /* init virtual mac address */ |
| 1971 | 2116 | nd->macaddr[0] = macaddr[0]; |
| 1972 | 2117 | nd->macaddr[1] = macaddr[1]; |
| ... | ... | @@ -1974,8 +2119,27 @@ int main(int argc, char **argv) |
| 1974 | 2119 | nd->macaddr[3] = macaddr[3]; |
| 1975 | 2120 | nd->macaddr[4] = macaddr[4]; |
| 1976 | 2121 | nd->macaddr[5] = macaddr[5] + i; |
| 2122 | + switch(net_if_type) { | |
| 2123 | +#if defined(CONFIG_SLIRP) | |
| 2124 | + case NET_IF_USER: | |
| 2125 | + net_slirp_init(nd); | |
| 2126 | + break; | |
| 2127 | +#endif | |
| 2128 | +#if !defined(_WIN32) | |
| 2129 | + case NET_IF_TUN: | |
| 2130 | + if (i < nb_tun_fds) { | |
| 2131 | + net_fd_init(nd, tun_fds[i]); | |
| 2132 | + } else { | |
| 2133 | + net_tun_init(nd); | |
| 2134 | + } | |
| 2135 | + break; | |
| 2136 | +#endif | |
| 2137 | + case NET_IF_DUMMY: | |
| 2138 | + default: | |
| 2139 | + net_dummy_init(nd); | |
| 2140 | + break; | |
| 2141 | + } | |
| 1977 | 2142 | } |
| 1978 | - net_init(); | |
| 1979 | 2143 | |
| 1980 | 2144 | /* init the memory */ |
| 1981 | 2145 | phys_ram_size = ram_size + vga_ram_size; |
| ... | ... | @@ -2058,7 +2222,7 @@ int main(int argc, char **argv) |
| 2058 | 2222 | } |
| 2059 | 2223 | if (fd_filename[i] != '\0') { |
| 2060 | 2224 | if (bdrv_open(fd_table[i], fd_filename[i], snapshot) < 0) { |
| 2061 | - fprintf(stderr, "qemu: could not open floppy disk image '%s\n", | |
| 2225 | + fprintf(stderr, "qemu: could not open floppy disk image '%s'\n", | |
| 2062 | 2226 | fd_filename[i]); |
| 2063 | 2227 | exit(1); |
| 2064 | 2228 | } | ... | ... |
vl.h
| ... | ... | @@ -132,29 +132,39 @@ void qemu_del_vm_stop_handler(VMStopHandler *cb, void *opaque); |
| 132 | 132 | void vm_start(void); |
| 133 | 133 | void vm_stop(int reason); |
| 134 | 134 | |
| 135 | +/* async I/O support */ | |
| 136 | + | |
| 137 | +typedef void IOReadHandler(void *opaque, const uint8_t *buf, int size); | |
| 138 | +typedef int IOCanRWHandler(void *opaque); | |
| 139 | + | |
| 140 | +int qemu_add_fd_read_handler(int fd, IOCanRWHandler *fd_can_read, | |
| 141 | + IOReadHandler *fd_read, void *opaque); | |
| 142 | +void qemu_del_fd_read_handler(int fd); | |
| 143 | + | |
| 135 | 144 | /* network redirectors support */ |
| 136 | 145 | |
| 137 | 146 | #define MAX_NICS 8 |
| 138 | 147 | |
| 139 | 148 | typedef struct NetDriverState { |
| 140 | - int fd; | |
| 149 | + int index; /* index number in QEMU */ | |
| 141 | 150 | uint8_t macaddr[6]; |
| 142 | 151 | char ifname[16]; |
| 152 | + void (*send_packet)(struct NetDriverState *nd, | |
| 153 | + const uint8_t *buf, int size); | |
| 154 | + void (*add_read_packet)(struct NetDriverState *nd, | |
| 155 | + IOCanRWHandler *fd_can_read, | |
| 156 | + IOReadHandler *fd_read, void *opaque); | |
| 157 | + /* tun specific data */ | |
| 158 | + int fd; | |
| 159 | + /* slirp specific data */ | |
| 143 | 160 | } NetDriverState; |
| 144 | 161 | |
| 145 | 162 | extern int nb_nics; |
| 146 | 163 | extern NetDriverState nd_table[MAX_NICS]; |
| 147 | 164 | |
| 148 | -void net_send_packet(NetDriverState *nd, const uint8_t *buf, int size); | |
| 149 | - | |
| 150 | -/* async I/O support */ | |
| 151 | - | |
| 152 | -typedef void IOReadHandler(void *opaque, const uint8_t *buf, int size); | |
| 153 | -typedef int IOCanRWHandler(void *opaque); | |
| 154 | - | |
| 155 | -int qemu_add_fd_read_handler(int fd, IOCanRWHandler *fd_can_read, | |
| 156 | - IOReadHandler *fd_read, void *opaque); | |
| 157 | -void qemu_del_fd_read_handler(int fd); | |
| 165 | +void qemu_send_packet(NetDriverState *nd, const uint8_t *buf, int size); | |
| 166 | +void qemu_add_read_packet(NetDriverState *nd, IOCanRWHandler *fd_can_read, | |
| 167 | + IOReadHandler *fd_read, void *opaque); | |
| 158 | 168 | |
| 159 | 169 | /* timers */ |
| 160 | 170 | |
| ... | ... | @@ -417,6 +427,7 @@ void serial_receive_break(SerialState *s); |
| 417 | 427 | void pic_set_irq(int irq, int level); |
| 418 | 428 | void pic_init(void); |
| 419 | 429 | uint32_t pic_intack_read(CPUState *env); |
| 430 | +void pic_info(void); | |
| 420 | 431 | |
| 421 | 432 | /* i8254.c */ |
| 422 | 433 | ... | ... |