X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?p=palacios.git;a=blobdiff_plain;f=geekos%2Fsrc%2Fgeekos%2Fsocket.c;fp=geekos%2Fsrc%2Fgeekos%2Fsocket.c;h=e67040b299380ccff197cce6a5938751ca780116;hp=0000000000000000000000000000000000000000;hb=ddc16b0737cf58f7aa90a69c6652cdf4090aec51;hpb=626595465a2c6987606a6bc697df65130ad8c2d3 diff --git a/geekos/src/geekos/socket.c b/geekos/src/geekos/socket.c new file mode 100644 index 0000000..e67040b --- /dev/null +++ b/geekos/src/geekos/socket.c @@ -0,0 +1,378 @@ +/* + * This file is part of the Palacios Virtual Machine Monitor developed + * by the V3VEE Project with funding from the United States National + * Science Foundation and the Department of Energy. + * + * The V3VEE Project is a joint project between Northwestern University + * and the University of New Mexico. You can find out more at + * http://www.v3vee.org + * + * Copyright (c) 2008, Jack Lange + * Copyright (c) 2008, Lei Xia + * Copyright (c) 2008, The V3VEE Project + * All rights reserved. + * + * Author: Jack Lange + * Author: Lei Xia + * + * This is free software. You are permitted to use, + * redistribute, and modify it as specified in the file "V3VEE_LICENSE". + */ + +#include +#include +#include + +#ifdef UIP + +#include +#include + +#include +#include +#include + +#define BUF ((struct uip_eth_hdr *)&uip_buf[0]) + +#define MAX_SOCKS 1024 +#define BUF_SIZE 1000 + +struct socket sockets[MAX_SOCKS]; + +void socket_appcall(void); +#ifndef UIP_APPCALL +#define UIP_APPCALL socket_appcall +#endif /* UIP_APPCALL */ + + +static int Packet_Received(struct NE2K_Packet_Info* info, uchar_t *pkt); +static void periodic_caller(int timer_id, void * arg); + +void init_socket_layer() { + + int i = 0; + bool iflag; + + + for (i = 0; i < MAX_SOCKS; i++) { + sockets[i].in_use = 0; + sockets[i].send_buf = NULL; + sockets[i].recv_buf = NULL; + sockets[i].state = CLOSED; + } + + //initiate uIP + uip_init(); + uip_arp_init(); + + //setup device driver + Init_Ne2k(&Packet_Received); + + iflag = Begin_Int_Atomic(); + Start_Timer(2, periodic_caller, NULL); + End_Int_Atomic(iflag); +} + +void set_ip_addr(uchar_t addr[4]) { + uip_ipaddr_t ipaddr; + uip_ipaddr(ipaddr, addr[0], addr[1], addr[2], addr[3]); /* Local IP address */ + uip_sethostaddr(ipaddr); +} + +static int allocate_socket_fd() { + int i = 0; + + for (i = 0; i < MAX_SOCKS; i++) { + if (sockets[i].in_use == 0) { + sockets[i].in_use = 1; + sockets[i].send_buf = create_ring_buffer(BUF_SIZE); + if (sockets[i].send_buf == NULL) + return -1; + sockets[i].recv_buf = create_ring_buffer(BUF_SIZE); + if (sockets[i].recv_buf == NULL){ + free_ring_buffer(sockets[i].send_buf); + return -1; + } + return i; + } + } + + return -1; +} + +static int release_socket_fd(int sockfd){ + if (sockfd >= 0 && sockfd < MAX_SOCKS){ + sockets[sockfd].in_use = 0; + free_ring_buffer(sockets[sockfd].send_buf); + free_ring_buffer(sockets[sockfd].recv_buf); + sockets[sockfd].send_buf = NULL; + sockets[sockfd].recv_buf = NULL; + sockets[sockfd].state = CLOSED; + } + + return 0; +} + + +struct socket * get_socket_from_fd(int fd) { + return &(sockets[fd]); +} + + +static void periodic_caller(int timer_id, void * arg) { + int i; + //handle the periodic calls of uIP + + //PrintBoth("Timer CALLBACK handler\n"); + + for(i = 0; i < UIP_CONNS; ++i) { + uip_periodic(i); + if(uip_len > 0) { + //devicedriver_send(); + PrintBoth("Sending Packet\n"); + NE2K_Transmit(uip_len); + } + } + for(i = 0; i < UIP_UDP_CONNS; i++) { + uip_udp_periodic(i); + if(uip_len > 0) { + //devicedriver_send(); + NE2K_Transmit(uip_len); + } + } +} + + +int connect(const uchar_t ip_addr[4], ushort_t port) { + int sockfd = -1; + sockfd = allocate_socket_fd(); + static uip_ipaddr_t ipaddr; + + if (sockfd == -1) { + return -1; + } + + uip_ipaddr(&ipaddr, ip_addr[0], ip_addr[1], ip_addr[2], ip_addr[3]); + + sockets[sockfd].con = uip_connect(&ipaddr, htons(port)); + + + if (sockets[sockfd].con == NULL){ + release_socket_fd(sockfd); + return -1; + } + + + PrintBoth("Connection start\n"); + Wait(&(sockets[sockfd].recv_wait_queue)); + + + PrintBoth("Connected\n"); + + + + + return sockfd; +} + +int recv(int sockfd, void * buf, uint_t len){ + uint_t recvlen; + + struct socket *sock = get_socket_from_fd(sockfd); + + + // here we need some lock mechnism, just disable interrupt may not work properly because recv() will be run as a kernel thread +buf_read: + recvlen = rb_read(sock->recv_buf, buf, len); + + if (recvlen == 0){ + Wait(&(sock->recv_wait_queue)); + goto buf_read; + } + + return recvlen; +} + + + +// a series of utilities to handle conncetion states +static void connected(int sockfd) { + struct socket * sock = get_socket_from_fd(sockfd); + + PrintBoth("Connected Interrupt\n"); + + sock->state = ESTABLISHED; + + Wake_Up(&(sock->recv_wait_queue)); +} + +static void closed(int sockfd){ + +} + +static void acked(int sockfd){ + +} + +static void newdata(int sockfd){ + uint_t len; + char *dataptr; + uint_t wrlen; + struct socket *sock; + + len = uip_datalen(); + dataptr = (char *)uip_appdata; + + if (len == 0) + return; + + sock = get_socket_from_fd(sockfd); + + wrlen = rb_write(sock->recv_buf, dataptr, len); + + if (wrlen < len){ //write error, what should I do? + return; + } + + Wake_Up(&(sock->recv_wait_queue)); + + return; + +} + +// not finished yet +static void send_to_driver(int sockfd) { + + PrintBoth("Sending data to driver\n"); + +} + + + +int send(int sockfd, void * buf, uint_t len) { + struct socket * sock = get_socket_from_fd(sockfd); + //int mss = uip_mss(); + //int pending_bytes = rb_data_len(sock->send_buf); + //int len = (mss < pending_bytes) ? mss: pending_bytes; + int bytes_read = 0; + uchar_t * send_buf = uip_appdata; + + bytes_read = rb_peek(sock->send_buf, send_buf, len); + + if (bytes_read == 0) { + // no packet for send + return -1; + } + + uip_send(send_buf, len); + + return len; +} + + + +//get the socket id by the local tcp port +static int get_socket_from_port(ushort_t lport) { + int i; + + + for (i = 0; i < MAX_SOCKS; i++){ + if (sockets[i].con->lport == lport) { + return i; + } + } + + return -1; +} + + + +void socket_appcall(void) { + + int sockfd; + + sockfd = get_socket_from_port(uip_conn->lport); + + PrintBoth("Appcall\n"); + + + if (sockfd == -1) { + return; + } + + if (uip_connected()) { + connected(sockfd); + + } + + if (uip_closed() ||uip_aborted() ||uip_timedout()) { + closed(sockfd); + return; + } + + if (uip_acked()) { + acked(sockfd); + } + + if (uip_newdata()) { + newdata(sockfd); + } + + if (uip_rexmit() || + uip_newdata() || + uip_acked() || + uip_connected() || + uip_poll()) { + send_to_driver(sockfd); + } +} + + + + +static int Packet_Received(struct NE2K_Packet_Info * info, uchar_t * pkt) { + //int i; + uip_len = info->size; + + // for (i = 0; i < info->size; i++) { + // uip_buf[i] = *(pkt + i); + //} + + PrintBoth("Packet REceived\n"); + + memcpy(uip_buf, pkt, uip_len); + + + Free(pkt); + + if (BUF->type == htons(UIP_ETHTYPE_ARP)) { + PrintBoth("ARP PACKET\n"); + + uip_arp_arpin(); + + + if (uip_len > 0) { + PrintBoth("Transmitting\n"); + NE2K_Transmit(uip_len); + } + + + } else { + PrintBoth("Data PACKET\n"); + uip_arp_ipin(); + uip_input(); + + + if (uip_len > 0) { + PrintBoth("Transmitting\n"); + uip_arp_out(); + NE2K_Transmit(uip_len); + } + + } + + return 0; +} + + +#endif /* UIP */