1 #include "kvm/uip.h" 2 3 #include <kvm/kvm.h> 4 #include <linux/virtio_net.h> 5 #include <linux/kernel.h> 6 #include <linux/list.h> 7 #include <arpa/inet.h> 8 9 static int uip_tcp_socket_close(struct uip_tcp_socket *sk, int how) 10 { 11 shutdown(sk->fd, how); 12 13 if (sk->write_done && sk->read_done) { 14 shutdown(sk->fd, SHUT_RDWR); 15 close(sk->fd); 16 17 mutex_lock(sk->lock); 18 list_del(&sk->list); 19 mutex_unlock(sk->lock); 20 21 free(sk); 22 } 23 24 return 0; 25 } 26 27 static struct uip_tcp_socket *uip_tcp_socket_find(struct uip_tx_arg *arg, u32 sip, u32 dip, u16 sport, u16 dport) 28 { 29 struct list_head *sk_head; 30 pthread_mutex_t *sk_lock; 31 struct uip_tcp_socket *sk; 32 33 sk_head = &arg->info->tcp_socket_head; 34 sk_lock = &arg->info->tcp_socket_lock; 35 36 mutex_lock(sk_lock); 37 list_for_each_entry(sk, sk_head, list) { 38 if (sk->sip == sip && sk->dip == dip && sk->sport == sport && sk->dport == dport) { 39 mutex_unlock(sk_lock); 40 return sk; 41 } 42 } 43 mutex_unlock(sk_lock); 44 45 return NULL; 46 } 47 48 static struct uip_tcp_socket *uip_tcp_socket_alloc(struct uip_tx_arg *arg, u32 sip, u32 dip, u16 sport, u16 dport) 49 { 50 struct list_head *sk_head; 51 struct uip_tcp_socket *sk; 52 pthread_mutex_t *sk_lock; 53 struct uip_tcp *tcp; 54 struct uip_ip *ip; 55 int ret; 56 57 tcp = (struct uip_tcp *)arg->eth; 58 ip = (struct uip_ip *)arg->eth; 59 60 sk_head = &arg->info->tcp_socket_head; 61 sk_lock = &arg->info->tcp_socket_lock; 62 63 sk = malloc(sizeof(*sk)); 64 memset(sk, 0, sizeof(*sk)); 65 66 sk->lock = sk_lock; 67 sk->info = arg->info; 68 69 sk->fd = socket(AF_INET, SOCK_STREAM, 0); 70 sk->addr.sin_family = AF_INET; 71 sk->addr.sin_port = dport; 72 sk->addr.sin_addr.s_addr = dip; 73 74 pthread_cond_init(&sk->cond, NULL); 75 76 if (ntohl(dip) == arg->info->host_ip) 77 sk->addr.sin_addr.s_addr = inet_addr("127.0.0.1"); 78 79 ret = connect(sk->fd, (struct sockaddr *)&sk->addr, sizeof(sk->addr)); 80 if (ret) { 81 free(sk); 82 return NULL; 83 } 84 85 sk->sip = ip->sip; 86 sk->dip = ip->dip; 87 sk->sport = tcp->sport; 88 sk->dport = tcp->dport; 89 90 mutex_lock(sk_lock); 91 list_add_tail(&sk->list, sk_head); 92 mutex_unlock(sk_lock); 93 94 return sk; 95 } 96 97 static int uip_tcp_payload_send(struct uip_tcp_socket *sk, u8 flag, u16 payload_len) 98 { 99 struct uip_info *info; 100 struct uip_eth *eth2; 101 struct uip_tcp *tcp2; 102 struct uip_buf *buf; 103 struct uip_ip *ip2; 104 105 info = sk->info; 106 107 /* 108 * Get free buffer to send data to guest 109 */ 110 buf = uip_buf_get_free(info); 111 112 /* 113 * Cook a ethernet frame 114 */ 115 tcp2 = (struct uip_tcp *)buf->eth; 116 eth2 = (struct uip_eth *)buf->eth; 117 ip2 = (struct uip_ip *)buf->eth; 118 119 eth2->src = info->host_mac; 120 eth2->dst = info->guest_mac; 121 eth2->type = htons(UIP_ETH_P_IP); 122 123 ip2->vhl = UIP_IP_VER_4 | UIP_IP_HDR_LEN; 124 ip2->tos = 0; 125 ip2->id = 0; 126 ip2->flgfrag = 0; 127 ip2->ttl = UIP_IP_TTL; 128 ip2->proto = UIP_IP_P_TCP; 129 ip2->csum = 0; 130 ip2->sip = sk->dip; 131 ip2->dip = sk->sip; 132 133 tcp2->sport = sk->dport; 134 tcp2->dport = sk->sport; 135 tcp2->seq = htonl(sk->seq_server); 136 tcp2->ack = htonl(sk->ack_server); 137 /* 138 * Diable TCP options, tcp hdr len equals 20 bytes 139 */ 140 tcp2->off = UIP_TCP_HDR_LEN; 141 tcp2->flg = flag; 142 tcp2->win = htons(UIP_TCP_WIN_SIZE); 143 tcp2->csum = 0; 144 tcp2->urgent = 0; 145 146 if (payload_len > 0) 147 memcpy(uip_tcp_payload(tcp2), sk->payload, payload_len); 148 149 ip2->len = htons(uip_tcp_hdrlen(tcp2) + payload_len + uip_ip_hdrlen(ip2)); 150 ip2->csum = uip_csum_ip(ip2); 151 tcp2->csum = uip_csum_tcp(tcp2); 152 153 /* 154 * virtio_net_hdr 155 */ 156 buf->vnet_len = sizeof(struct virtio_net_hdr); 157 memset(buf->vnet, 0, buf->vnet_len); 158 159 buf->eth_len = ntohs(ip2->len) + uip_eth_hdrlen(&ip2->eth); 160 161 /* 162 * Increase server seq 163 */ 164 sk->seq_server += payload_len; 165 166 /* 167 * Send data received from socket to guest 168 */ 169 uip_buf_set_used(info, buf); 170 171 return 0; 172 } 173 174 static void *uip_tcp_socket_thread(void *p) 175 { 176 struct uip_tcp_socket *sk; 177 int len, left, ret; 178 u8 *payload, *pos; 179 180 kvm__set_thread_name("uip-tcp"); 181 182 sk = p; 183 184 payload = malloc(UIP_MAX_TCP_PAYLOAD); 185 if (!payload) 186 goto out; 187 188 while (1) { 189 pos = payload; 190 191 ret = read(sk->fd, payload, UIP_MAX_TCP_PAYLOAD); 192 193 if (ret <= 0 || ret > UIP_MAX_TCP_PAYLOAD) 194 goto out; 195 196 left = ret; 197 198 while (left > 0) { 199 mutex_lock(sk->lock); 200 while ((len = sk->guest_acked + sk->window_size - sk->seq_server) <= 0) 201 pthread_cond_wait(&sk->cond, sk->lock); 202 mutex_unlock(sk->lock); 203 204 sk->payload = pos; 205 if (len > left) 206 len = left; 207 if (len > UIP_MAX_TCP_PAYLOAD) 208 len = UIP_MAX_TCP_PAYLOAD; 209 left -= len; 210 pos += len; 211 212 uip_tcp_payload_send(sk, UIP_TCP_FLAG_ACK, len); 213 } 214 } 215 216 out: 217 /* 218 * Close server to guest TCP connection 219 */ 220 uip_tcp_socket_close(sk, SHUT_RD); 221 222 uip_tcp_payload_send(sk, UIP_TCP_FLAG_FIN | UIP_TCP_FLAG_ACK, 0); 223 sk->seq_server += 1; 224 225 sk->read_done = 1; 226 227 free(payload); 228 pthread_exit(NULL); 229 230 return NULL; 231 } 232 233 static int uip_tcp_socket_receive(struct uip_tcp_socket *sk) 234 { 235 if (sk->thread == 0) 236 return pthread_create(&sk->thread, NULL, uip_tcp_socket_thread, (void *)sk); 237 238 return 0; 239 } 240 241 static int uip_tcp_socket_send(struct uip_tcp_socket *sk, struct uip_tcp *tcp) 242 { 243 int len; 244 int ret; 245 u8 *payload; 246 247 if (sk->write_done) 248 return 0; 249 250 payload = uip_tcp_payload(tcp); 251 len = uip_tcp_payloadlen(tcp); 252 253 ret = write(sk->fd, payload, len); 254 if (ret != len) 255 pr_warning("tcp send error"); 256 257 return ret; 258 } 259 260 int uip_tx_do_ipv4_tcp(struct uip_tx_arg *arg) 261 { 262 struct uip_tcp_socket *sk; 263 struct uip_tcp *tcp; 264 struct uip_ip *ip; 265 int ret; 266 267 tcp = (struct uip_tcp *)arg->eth; 268 ip = (struct uip_ip *)arg->eth; 269 270 /* 271 * Guest is trying to start a TCP session, let's fake SYN-ACK to guest 272 */ 273 if (uip_tcp_is_syn(tcp)) { 274 sk = uip_tcp_socket_alloc(arg, ip->sip, ip->dip, tcp->sport, tcp->dport); 275 if (!sk) 276 return -1; 277 278 sk->window_size = ntohs(tcp->win); 279 280 /* 281 * Setup ISN number 282 */ 283 sk->isn_guest = uip_tcp_isn(tcp); 284 sk->isn_server = uip_tcp_isn_alloc(); 285 286 sk->seq_server = sk->isn_server; 287 sk->ack_server = sk->isn_guest + 1; 288 uip_tcp_payload_send(sk, UIP_TCP_FLAG_SYN | UIP_TCP_FLAG_ACK, 0); 289 sk->seq_server += 1; 290 291 /* 292 * Start receive thread for data from remote to guest 293 */ 294 uip_tcp_socket_receive(sk); 295 296 goto out; 297 } 298 299 /* 300 * Find socket we have allocated 301 */ 302 sk = uip_tcp_socket_find(arg, ip->sip, ip->dip, tcp->sport, tcp->dport); 303 if (!sk) 304 return -1; 305 306 mutex_lock(sk->lock); 307 sk->window_size = ntohs(tcp->win); 308 sk->guest_acked = ntohl(tcp->ack); 309 pthread_cond_signal(&sk->cond); 310 mutex_unlock(sk->lock); 311 312 if (uip_tcp_is_fin(tcp)) { 313 if (sk->write_done) 314 goto out; 315 316 sk->write_done = 1; 317 sk->ack_server += 1; 318 uip_tcp_payload_send(sk, UIP_TCP_FLAG_ACK, 0); 319 320 /* 321 * Close guest to server TCP connection 322 */ 323 uip_tcp_socket_close(sk, SHUT_WR); 324 325 goto out; 326 } 327 328 /* 329 * Ignore guest to server frames with zero tcp payload 330 */ 331 if (uip_tcp_payloadlen(tcp) == 0) 332 goto out; 333 334 /* 335 * Sent out TCP data to remote host 336 */ 337 ret = uip_tcp_socket_send(sk, tcp); 338 if (ret < 0) 339 return -1; 340 /* 341 * Send ACK to guest imediately 342 */ 343 sk->ack_server += ret; 344 uip_tcp_payload_send(sk, UIP_TCP_FLAG_ACK, 0); 345 346 out: 347 return 0; 348 } 349