2 * This file is part of the Palacios Virtual Machine Monitor developed
3 * by the V3VEE Project with funding from the United States National
4 * Science Foundation and the Department of Energy.
6 * The V3VEE Project is a joint project between Northwestern University
7 * and the University of New Mexico. You can find out more at
10 * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu>
11 * Copyright (c) 2008, Lei Xia <xiaxlei@gmail.com>
12 * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org>
13 * All rights reserved.
15 * Author: Jack Lange <jarusl@cs.northwestern.edu>
16 * Author: Lei Xia <xiaxlei@gmail.com>
18 * This is free software. You are permitted to use,
19 * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
22 #include <geekos/socket.h>
23 #include <geekos/malloc.h>
24 #include <geekos/ne2k.h>
29 #include <uip/uip_arp.h>
31 #include <geekos/vmm_stubs.h>
32 #include <geekos/debug.h>
33 #include <geekos/timer.h>
35 #define BUF ((struct uip_eth_hdr *)&uip_buf[0])
37 #define MAX_SOCKS 1024
40 struct socket sockets[MAX_SOCKS];
42 void socket_appcall(void);
44 #define UIP_APPCALL socket_appcall
45 #endif /* UIP_APPCALL */
48 static int Packet_Received(struct NE2K_Packet_Info* info, uchar_t *pkt);
49 static void periodic_caller(int timer_id, void * arg);
51 void init_socket_layer() {
57 for (i = 0; i < MAX_SOCKS; i++) {
58 sockets[i].in_use = 0;
59 sockets[i].send_buf = NULL;
60 sockets[i].recv_buf = NULL;
61 sockets[i].state = CLOSED;
69 Init_Ne2k(&Packet_Received);
71 iflag = Begin_Int_Atomic();
72 Start_Timer(2, periodic_caller, NULL);
73 End_Int_Atomic(iflag);
76 void set_ip_addr(uchar_t addr[4]) {
78 uip_ipaddr(ipaddr, addr[0], addr[1], addr[2], addr[3]); /* Local IP address */
79 uip_sethostaddr(ipaddr);
82 static int allocate_socket_fd() {
85 for (i = 0; i < MAX_SOCKS; i++) {
86 if (sockets[i].in_use == 0) {
87 sockets[i].in_use = 1;
88 sockets[i].send_buf = create_ring_buffer(BUF_SIZE);
89 if (sockets[i].send_buf == NULL)
91 sockets[i].recv_buf = create_ring_buffer(BUF_SIZE);
92 if (sockets[i].recv_buf == NULL){
93 free_ring_buffer(sockets[i].send_buf);
103 static int release_socket_fd(int sockfd){
104 if (sockfd >= 0 && sockfd < MAX_SOCKS){
105 sockets[sockfd].in_use = 0;
106 free_ring_buffer(sockets[sockfd].send_buf);
107 free_ring_buffer(sockets[sockfd].recv_buf);
108 sockets[sockfd].send_buf = NULL;
109 sockets[sockfd].recv_buf = NULL;
110 sockets[sockfd].state = CLOSED;
117 struct socket * get_socket_from_fd(int fd) {
118 return &(sockets[fd]);
122 static void periodic_caller(int timer_id, void * arg) {
124 //handle the periodic calls of uIP
126 //PrintBoth("Timer CALLBACK handler\n");
128 for(i = 0; i < UIP_CONNS; ++i) {
131 //devicedriver_send();
132 PrintBoth("Sending Packet\n");
133 NE2K_Transmit(uip_len);
136 for(i = 0; i < UIP_UDP_CONNS; i++) {
139 //devicedriver_send();
140 NE2K_Transmit(uip_len);
146 int connect(const uchar_t ip_addr[4], ushort_t port) {
148 sockfd = allocate_socket_fd();
149 static uip_ipaddr_t ipaddr;
155 uip_ipaddr(&ipaddr, ip_addr[0], ip_addr[1], ip_addr[2], ip_addr[3]);
157 sockets[sockfd].con = uip_connect(&ipaddr, htons(port));
160 if (sockets[sockfd].con == NULL){
161 release_socket_fd(sockfd);
166 PrintBoth("Connection start\n");
167 Wait(&(sockets[sockfd].recv_wait_queue));
170 PrintBoth("Connected\n");
178 int recv(int sockfd, void * buf, uint_t len){
181 struct socket *sock = get_socket_from_fd(sockfd);
184 // here we need some lock mechnism, just disable interrupt may not work properly because recv() will be run as a kernel thread
186 recvlen = rb_read(sock->recv_buf, buf, len);
189 Wait(&(sock->recv_wait_queue));
198 // a series of utilities to handle conncetion states
199 static void connected(int sockfd) {
200 struct socket * sock = get_socket_from_fd(sockfd);
202 PrintBoth("Connected Interrupt\n");
204 sock->state = ESTABLISHED;
206 Wake_Up(&(sock->recv_wait_queue));
209 static void closed(int sockfd){
213 static void acked(int sockfd){
217 static void newdata(int sockfd){
224 dataptr = (char *)uip_appdata;
229 sock = get_socket_from_fd(sockfd);
231 wrlen = rb_write(sock->recv_buf, dataptr, len);
233 if (wrlen < len){ //write error, what should I do?
237 Wake_Up(&(sock->recv_wait_queue));
244 static void send_to_driver(int sockfd) {
246 PrintBoth("Sending data to driver\n");
252 int send(int sockfd, void * buf, uint_t len) {
253 struct socket * sock = get_socket_from_fd(sockfd);
254 //int mss = uip_mss();
255 //int pending_bytes = rb_data_len(sock->send_buf);
256 //int len = (mss < pending_bytes) ? mss: pending_bytes;
258 uchar_t * send_buf = uip_appdata;
260 bytes_read = rb_peek(sock->send_buf, send_buf, len);
262 if (bytes_read == 0) {
263 // no packet for send
267 uip_send(send_buf, len);
274 //get the socket id by the local tcp port
275 static int get_socket_from_port(ushort_t lport) {
279 for (i = 0; i < MAX_SOCKS; i++){
280 if (sockets[i].con->lport == lport) {
290 void socket_appcall(void) {
294 sockfd = get_socket_from_port(uip_conn->lport);
296 PrintBoth("Appcall\n");
303 if (uip_connected()) {
308 if (uip_closed() ||uip_aborted() ||uip_timedout()) {
326 send_to_driver(sockfd);
333 static int Packet_Received(struct NE2K_Packet_Info * info, uchar_t * pkt) {
335 uip_len = info->size;
337 // for (i = 0; i < info->size; i++) {
338 // uip_buf[i] = *(pkt + i);
341 PrintBoth("Packet REceived\n");
343 memcpy(uip_buf, pkt, uip_len);
348 if (BUF->type == htons(UIP_ETHTYPE_ARP)) {
349 PrintBoth("ARP PACKET\n");
355 PrintBoth("Transmitting\n");
356 NE2K_Transmit(uip_len);
361 PrintBoth("Data PACKET\n");
367 PrintBoth("Transmitting\n");
369 NE2K_Transmit(uip_len);