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,6 +23,7 @@ | ||
23 | */ | 23 | */ |
24 | #include "qemu-common.h" | 24 | #include "qemu-common.h" |
25 | #include "slirp.h" | 25 | #include "slirp.h" |
26 | +#include "hw/hw.h" | ||
26 | 27 | ||
27 | /* host address */ | 28 | /* host address */ |
28 | struct in_addr our_addr; | 29 | struct in_addr our_addr; |
@@ -166,6 +167,9 @@ static void slirp_cleanup(void) | @@ -166,6 +167,9 @@ static void slirp_cleanup(void) | ||
166 | } | 167 | } |
167 | #endif | 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 | void slirp_init(int restrict, char *special_ip) | 173 | void slirp_init(int restrict, char *special_ip) |
170 | { | 174 | { |
171 | // debug_init("/tmp/slirp.log", DEBUG_DEFAULT); | 175 | // debug_init("/tmp/slirp.log", DEBUG_DEFAULT); |
@@ -201,6 +205,7 @@ void slirp_init(int restrict, char *special_ip) | @@ -201,6 +205,7 @@ void slirp_init(int restrict, char *special_ip) | ||
201 | inet_aton(slirp_special_ip, &special_addr); | 205 | inet_aton(slirp_special_ip, &special_addr); |
202 | alias_addr.s_addr = special_addr.s_addr | htonl(CTL_ALIAS); | 206 | alias_addr.s_addr = special_addr.s_addr | htonl(CTL_ALIAS); |
203 | getouraddr(); | 207 | getouraddr(); |
208 | + register_savevm("slirp", 0, 1, slirp_state_save, slirp_state_load, NULL); | ||
204 | } | 209 | } |
205 | 210 | ||
206 | #define CONN_CANFSEND(so) (((so)->so_state & (SS_FCANTSENDMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED) | 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,3 +814,225 @@ void slirp_socket_recv(int addr_low_byte, int guest_port, const uint8_t *buf, | ||
809 | if (ret > 0) | 814 | if (ret > 0) |
810 | tcp_output(sototcpcb(so)); | 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 | +} |