Commit 062e55272e21d45bd8056fb5d8745ec8f22961ff
1 parent
49ec9b40
Add support for vmchannel socket migration (Gleb Natapov)
Signed-off-by: Gleb Natapov <gleb@redhat.com> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com> git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6243 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
227 additions
and
0 deletions
slirp/slirp.c
| ... | ... | @@ -23,6 +23,7 @@ |
| 23 | 23 | */ |
| 24 | 24 | #include "qemu-common.h" |
| 25 | 25 | #include "slirp.h" |
| 26 | +#include "hw/hw.h" | |
| 26 | 27 | |
| 27 | 28 | /* host address */ |
| 28 | 29 | struct in_addr our_addr; |
| ... | ... | @@ -166,6 +167,9 @@ static void slirp_cleanup(void) |
| 166 | 167 | } |
| 167 | 168 | #endif |
| 168 | 169 | |
| 170 | +static void slirp_state_save(QEMUFile *f, void *opaque); | |
| 171 | +static int slirp_state_load(QEMUFile *f, void *opaque, int version_id); | |
| 172 | + | |
| 169 | 173 | void slirp_init(int restrict, char *special_ip) |
| 170 | 174 | { |
| 171 | 175 | // debug_init("/tmp/slirp.log", DEBUG_DEFAULT); |
| ... | ... | @@ -201,6 +205,7 @@ void slirp_init(int restrict, char *special_ip) |
| 201 | 205 | inet_aton(slirp_special_ip, &special_addr); |
| 202 | 206 | alias_addr.s_addr = special_addr.s_addr | htonl(CTL_ALIAS); |
| 203 | 207 | getouraddr(); |
| 208 | + register_savevm("slirp", 0, 1, slirp_state_save, slirp_state_load, NULL); | |
| 204 | 209 | } |
| 205 | 210 | |
| 206 | 211 | #define CONN_CANFSEND(so) (((so)->so_state & (SS_FCANTSENDMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED) |
| ... | ... | @@ -809,3 +814,225 @@ void slirp_socket_recv(int addr_low_byte, int guest_port, const uint8_t *buf, |
| 809 | 814 | if (ret > 0) |
| 810 | 815 | tcp_output(sototcpcb(so)); |
| 811 | 816 | } |
| 817 | + | |
| 818 | +static void slirp_tcp_save(QEMUFile *f, struct tcpcb *tp) | |
| 819 | +{ | |
| 820 | + int i; | |
| 821 | + | |
| 822 | + qemu_put_sbe16(f, tp->t_state); | |
| 823 | + for (i = 0; i < TCPT_NTIMERS; i++) | |
| 824 | + qemu_put_sbe16(f, tp->t_timer[i]); | |
| 825 | + qemu_put_sbe16(f, tp->t_rxtshift); | |
| 826 | + qemu_put_sbe16(f, tp->t_rxtcur); | |
| 827 | + qemu_put_sbe16(f, tp->t_dupacks); | |
| 828 | + qemu_put_be16(f, tp->t_maxseg); | |
| 829 | + qemu_put_sbyte(f, tp->t_force); | |
| 830 | + qemu_put_be16(f, tp->t_flags); | |
| 831 | + qemu_put_be32(f, tp->snd_una); | |
| 832 | + qemu_put_be32(f, tp->snd_nxt); | |
| 833 | + qemu_put_be32(f, tp->snd_up); | |
| 834 | + qemu_put_be32(f, tp->snd_wl1); | |
| 835 | + qemu_put_be32(f, tp->snd_wl2); | |
| 836 | + qemu_put_be32(f, tp->iss); | |
| 837 | + qemu_put_be32(f, tp->snd_wnd); | |
| 838 | + qemu_put_be32(f, tp->rcv_wnd); | |
| 839 | + qemu_put_be32(f, tp->rcv_nxt); | |
| 840 | + qemu_put_be32(f, tp->rcv_up); | |
| 841 | + qemu_put_be32(f, tp->irs); | |
| 842 | + qemu_put_be32(f, tp->rcv_adv); | |
| 843 | + qemu_put_be32(f, tp->snd_max); | |
| 844 | + qemu_put_be32(f, tp->snd_cwnd); | |
| 845 | + qemu_put_be32(f, tp->snd_ssthresh); | |
| 846 | + qemu_put_sbe16(f, tp->t_idle); | |
| 847 | + qemu_put_sbe16(f, tp->t_rtt); | |
| 848 | + qemu_put_be32(f, tp->t_rtseq); | |
| 849 | + qemu_put_sbe16(f, tp->t_srtt); | |
| 850 | + qemu_put_sbe16(f, tp->t_rttvar); | |
| 851 | + qemu_put_be16(f, tp->t_rttmin); | |
| 852 | + qemu_put_be32(f, tp->max_sndwnd); | |
| 853 | + qemu_put_byte(f, tp->t_oobflags); | |
| 854 | + qemu_put_byte(f, tp->t_iobc); | |
| 855 | + qemu_put_sbe16(f, tp->t_softerror); | |
| 856 | + qemu_put_byte(f, tp->snd_scale); | |
| 857 | + qemu_put_byte(f, tp->rcv_scale); | |
| 858 | + qemu_put_byte(f, tp->request_r_scale); | |
| 859 | + qemu_put_byte(f, tp->requested_s_scale); | |
| 860 | + qemu_put_be32(f, tp->ts_recent); | |
| 861 | + qemu_put_be32(f, tp->ts_recent_age); | |
| 862 | + qemu_put_be32(f, tp->last_ack_sent); | |
| 863 | +} | |
| 864 | + | |
| 865 | +static void slirp_sbuf_save(QEMUFile *f, struct sbuf *sbuf) | |
| 866 | +{ | |
| 867 | + uint32_t off; | |
| 868 | + | |
| 869 | + qemu_put_be32(f, sbuf->sb_cc); | |
| 870 | + qemu_put_be32(f, sbuf->sb_datalen); | |
| 871 | + off = (uint32_t)(sbuf->sb_wptr - sbuf->sb_data); | |
| 872 | + qemu_put_sbe32(f, off); | |
| 873 | + off = (uint32_t)(sbuf->sb_rptr - sbuf->sb_data); | |
| 874 | + qemu_put_sbe32(f, off); | |
| 875 | + qemu_put_buffer(f, (unsigned char*)sbuf->sb_data, sbuf->sb_datalen); | |
| 876 | +} | |
| 877 | + | |
| 878 | +static void slirp_socket_save(QEMUFile *f, struct socket *so) | |
| 879 | +{ | |
| 880 | + qemu_put_be32(f, so->so_urgc); | |
| 881 | + qemu_put_be32(f, so->so_faddr.s_addr); | |
| 882 | + qemu_put_be32(f, so->so_laddr.s_addr); | |
| 883 | + qemu_put_be16(f, so->so_fport); | |
| 884 | + qemu_put_be16(f, so->so_lport); | |
| 885 | + qemu_put_byte(f, so->so_iptos); | |
| 886 | + qemu_put_byte(f, so->so_emu); | |
| 887 | + qemu_put_byte(f, so->so_type); | |
| 888 | + qemu_put_be32(f, so->so_state); | |
| 889 | + slirp_sbuf_save(f, &so->so_rcv); | |
| 890 | + slirp_sbuf_save(f, &so->so_snd); | |
| 891 | + slirp_tcp_save(f, so->so_tcpcb); | |
| 892 | +} | |
| 893 | + | |
| 894 | +static void slirp_state_save(QEMUFile *f, void *opaque) | |
| 895 | +{ | |
| 896 | + struct ex_list *ex_ptr; | |
| 897 | + | |
| 898 | + for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) | |
| 899 | + if (ex_ptr->ex_pty == 3) { | |
| 900 | + struct socket *so; | |
| 901 | + so = slirp_find_ctl_socket(ex_ptr->ex_addr, ntohs(ex_ptr->ex_fport)); | |
| 902 | + if (!so) | |
| 903 | + continue; | |
| 904 | + | |
| 905 | + qemu_put_byte(f, 42); | |
| 906 | + slirp_socket_save(f, so); | |
| 907 | + } | |
| 908 | + qemu_put_byte(f, 0); | |
| 909 | +} | |
| 910 | + | |
| 911 | +static void slirp_tcp_load(QEMUFile *f, struct tcpcb *tp) | |
| 912 | +{ | |
| 913 | + int i; | |
| 914 | + | |
| 915 | + tp->t_state = qemu_get_sbe16(f); | |
| 916 | + for (i = 0; i < TCPT_NTIMERS; i++) | |
| 917 | + tp->t_timer[i] = qemu_get_sbe16(f); | |
| 918 | + tp->t_rxtshift = qemu_get_sbe16(f); | |
| 919 | + tp->t_rxtcur = qemu_get_sbe16(f); | |
| 920 | + tp->t_dupacks = qemu_get_sbe16(f); | |
| 921 | + tp->t_maxseg = qemu_get_be16(f); | |
| 922 | + tp->t_force = qemu_get_sbyte(f); | |
| 923 | + tp->t_flags = qemu_get_be16(f); | |
| 924 | + tp->snd_una = qemu_get_be32(f); | |
| 925 | + tp->snd_nxt = qemu_get_be32(f); | |
| 926 | + tp->snd_up = qemu_get_be32(f); | |
| 927 | + tp->snd_wl1 = qemu_get_be32(f); | |
| 928 | + tp->snd_wl2 = qemu_get_be32(f); | |
| 929 | + tp->iss = qemu_get_be32(f); | |
| 930 | + tp->snd_wnd = qemu_get_be32(f); | |
| 931 | + tp->rcv_wnd = qemu_get_be32(f); | |
| 932 | + tp->rcv_nxt = qemu_get_be32(f); | |
| 933 | + tp->rcv_up = qemu_get_be32(f); | |
| 934 | + tp->irs = qemu_get_be32(f); | |
| 935 | + tp->rcv_adv = qemu_get_be32(f); | |
| 936 | + tp->snd_max = qemu_get_be32(f); | |
| 937 | + tp->snd_cwnd = qemu_get_be32(f); | |
| 938 | + tp->snd_ssthresh = qemu_get_be32(f); | |
| 939 | + tp->t_idle = qemu_get_sbe16(f); | |
| 940 | + tp->t_rtt = qemu_get_sbe16(f); | |
| 941 | + tp->t_rtseq = qemu_get_be32(f); | |
| 942 | + tp->t_srtt = qemu_get_sbe16(f); | |
| 943 | + tp->t_rttvar = qemu_get_sbe16(f); | |
| 944 | + tp->t_rttmin = qemu_get_be16(f); | |
| 945 | + tp->max_sndwnd = qemu_get_be32(f); | |
| 946 | + tp->t_oobflags = qemu_get_byte(f); | |
| 947 | + tp->t_iobc = qemu_get_byte(f); | |
| 948 | + tp->t_softerror = qemu_get_sbe16(f); | |
| 949 | + tp->snd_scale = qemu_get_byte(f); | |
| 950 | + tp->rcv_scale = qemu_get_byte(f); | |
| 951 | + tp->request_r_scale = qemu_get_byte(f); | |
| 952 | + tp->requested_s_scale = qemu_get_byte(f); | |
| 953 | + tp->ts_recent = qemu_get_be32(f); | |
| 954 | + tp->ts_recent_age = qemu_get_be32(f); | |
| 955 | + tp->last_ack_sent = qemu_get_be32(f); | |
| 956 | + tcp_template(tp); | |
| 957 | +} | |
| 958 | + | |
| 959 | +static int slirp_sbuf_load(QEMUFile *f, struct sbuf *sbuf) | |
| 960 | +{ | |
| 961 | + uint32_t off, sb_cc, sb_datalen; | |
| 962 | + | |
| 963 | + sb_cc = qemu_get_be32(f); | |
| 964 | + sb_datalen = qemu_get_be32(f); | |
| 965 | + | |
| 966 | + sbreserve(sbuf, sb_datalen); | |
| 967 | + | |
| 968 | + if (sbuf->sb_datalen != sb_datalen) | |
| 969 | + return -ENOMEM; | |
| 970 | + | |
| 971 | + sbuf->sb_cc = sb_cc; | |
| 972 | + | |
| 973 | + off = qemu_get_sbe32(f); | |
| 974 | + sbuf->sb_wptr = sbuf->sb_data + off; | |
| 975 | + off = qemu_get_sbe32(f); | |
| 976 | + sbuf->sb_rptr = sbuf->sb_data + off; | |
| 977 | + qemu_get_buffer(f, (unsigned char*)sbuf->sb_data, sbuf->sb_datalen); | |
| 978 | + | |
| 979 | + return 0; | |
| 980 | +} | |
| 981 | + | |
| 982 | +static int slirp_socket_load(QEMUFile *f, struct socket *so) | |
| 983 | +{ | |
| 984 | + if (tcp_attach(so) < 0) | |
| 985 | + return -ENOMEM; | |
| 986 | + | |
| 987 | + so->so_urgc = qemu_get_be32(f); | |
| 988 | + so->so_faddr.s_addr = qemu_get_be32(f); | |
| 989 | + so->so_laddr.s_addr = qemu_get_be32(f); | |
| 990 | + so->so_fport = qemu_get_be16(f); | |
| 991 | + so->so_lport = qemu_get_be16(f); | |
| 992 | + so->so_iptos = qemu_get_byte(f); | |
| 993 | + so->so_emu = qemu_get_byte(f); | |
| 994 | + so->so_type = qemu_get_byte(f); | |
| 995 | + so->so_state = qemu_get_be32(f); | |
| 996 | + if (slirp_sbuf_load(f, &so->so_rcv) < 0) | |
| 997 | + return -ENOMEM; | |
| 998 | + if (slirp_sbuf_load(f, &so->so_snd) < 0) | |
| 999 | + return -ENOMEM; | |
| 1000 | + slirp_tcp_load(f, so->so_tcpcb); | |
| 1001 | + | |
| 1002 | + return 0; | |
| 1003 | +} | |
| 1004 | + | |
| 1005 | +static int slirp_state_load(QEMUFile *f, void *opaque, int version_id) | |
| 1006 | +{ | |
| 1007 | + struct ex_list *ex_ptr; | |
| 1008 | + int r; | |
| 1009 | + | |
| 1010 | + while ((r = qemu_get_byte(f))) { | |
| 1011 | + int ret; | |
| 1012 | + struct socket *so = socreate(); | |
| 1013 | + | |
| 1014 | + if (!so) | |
| 1015 | + return -ENOMEM; | |
| 1016 | + | |
| 1017 | + ret = slirp_socket_load(f, so); | |
| 1018 | + | |
| 1019 | + if (ret < 0) | |
| 1020 | + return ret; | |
| 1021 | + | |
| 1022 | + if ((so->so_faddr.s_addr & htonl(0xffffff00)) != special_addr.s_addr) | |
| 1023 | + return -EINVAL; | |
| 1024 | + | |
| 1025 | + for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) | |
| 1026 | + if (ex_ptr->ex_pty == 3 && | |
| 1027 | + (ntohl(so->so_faddr.s_addr) & 0xff) == ex_ptr->ex_addr && | |
| 1028 | + so->so_fport == ex_ptr->ex_fport) | |
| 1029 | + break; | |
| 1030 | + | |
| 1031 | + if (!ex_ptr) | |
| 1032 | + return -EINVAL; | |
| 1033 | + | |
| 1034 | + so->extra = ex_ptr->ex_exec; | |
| 1035 | + } | |
| 1036 | + | |
| 1037 | + return 0; | |
| 1038 | +} | ... | ... |