1/** 2 * \file 3 * \brief Echo server 4 */ 5 6/* 7 * Copyright (c) 2007-12 ETH Zurich. 8 * All rights reserved. 9 * 10 * This file is distributed under the terms in the attached LICENSE file. 11 * If you do not find this file, copies can be found by writing to: 12 * ETH Zurich D-INFK, Universitaetstrasse 6, CH-8092 Zurich. Attn: Systems Group. 13 */ 14 15#include <barrelfish/barrelfish.h> 16#include <stdio.h> 17#include <assert.h> 18#include <lwip/netif.h> 19#include <lwip/dhcp.h> 20#include <netif/etharp.h> 21#include <lwip/init.h> 22#include <lwip/tcp.h> 23#include <netif/bfeth.h> 24#include <trace/trace.h> 25#include <trace_definitions/trace_defs.h> 26#include "echoserver.h" 27 28 29extern void idc_print_statistics(void); 30extern void idc_print_cardinfo(void); 31 32extern uint64_t minbase, maxbase; 33 34#if TRACE_ONLY_SUB_NNET 35static size_t n64b = 0; 36#endif 37 38static void echo_server_close(struct tcp_pcb *tpcb) 39{ 40 tcp_arg(tpcb, NULL); 41 tcp_close(tpcb); 42} 43 44 45static void echo_server_err(void *arg, err_t err) 46{ 47 printf("echo_server_err! %p %d\n", arg, err); 48} 49 50 51static err_t echo_server_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, 52 err_t err) 53{ 54 int r; 55 if (p == NULL) { 56 // close the connection 57 echo_server_close(tpcb); 58 return ERR_OK; 59 } 60 61#if TRACE_ONLY_SUB_NNET 62 trace_event(TRACE_SUBSYS_NNET, TRACE_EVENT_NNET_RXAPPRCV, 63 0); 64#endif // TRACE_ONLY_SUB_NNET 65 66 /* don't send an immediate ack here, do it later with the data */ 67 tpcb->flags |= TF_ACK_DELAY; 68 assert(p->next == 0); 69 70 /*if ((p->tot_len > 2) && (p->tot_len < 200)) { 71 if (strncmp(p->payload, "stat", 4) == 0) { 72 idc_print_statistics(); 73 } 74 if (strncmp(p->payload, "cardinfo", 8) == 0) { 75 idc_print_cardinfo(); 76 } 77 if (strncmp(p->payload, "lwipinfo", 8) == 0) { 78 printf("echoserver's memory affinity: [0x%lx, 0x%lx]\n", 79 minbase, maxbase); 80 } 81 }*/ 82 83#if TRACE_ONLY_SUB_NNET 84 if (p->tot_len == 64) { 85 n64b++; 86 if (n64b == 5) { 87 trace_control(TRACE_EVENT(TRACE_SUBSYS_NNET, 88 TRACE_EVENT_NNET_START, 0), 89 TRACE_EVENT(TRACE_SUBSYS_NNET, 90 TRACE_EVENT_NNET_STOP, 0), 0); 91 trace_event(TRACE_SUBSYS_NNET, TRACE_EVENT_NNET_START, 0); 92 } else if (n64b == 8) { 93 trace_event(TRACE_SUBSYS_NNET, TRACE_EVENT_NNET_STOP, 0); 94 char* trbuf = malloc(4096*4096); 95 size_t length = trace_dump(trbuf, 4096*4096, NULL); 96 printf("%s\n", trbuf); 97 printf("length of buffer %zu\n", length); 98 free(trbuf); 99 } 100 } 101 102 103 trace_event(TRACE_SUBSYS_NNET, TRACE_EVENT_NNET_TXAPPSNT, 0); 104#endif 105 106 107 //XXX: can we do that without needing to copy it?? 108 r = tcp_write(tpcb, p->payload, p->len, TCP_WRITE_FLAG_COPY); 109 assert(r == ERR_OK); 110 111#if TRACE_ONLY_SUB_NNET 112 trace_event(TRACE_SUBSYS_NNET, TRACE_EVENT_NNET_TX_TCP_WRITE, 0); 113#endif 114 115 // make sure data gets sent immediately 116 r = tcp_output(tpcb); 117 assert(r == ERR_OK); 118 119#if TRACE_ONLY_SUB_NNET 120 trace_event(TRACE_SUBSYS_NNET, TRACE_EVENT_NNET_TX_TCP_OUTPUT, 0); 121#endif 122 123 tcp_recved(tpcb, p->len); 124#if TRACE_ONLY_SUB_NNET 125 trace_event(TRACE_SUBSYS_NNET, TRACE_EVENT_NNET_TX_TCP_RECV, 0); 126#endif 127 128 129 //now we can advertise a bigger window 130 pbuf_free(p); 131#if TRACE_ONLY_SUB_NNET 132 trace_event(TRACE_SUBSYS_NNET, TRACE_EVENT_NNET_TX_TCP_FREE, 0); 133#endif 134 135 136 return ERR_OK; 137} 138 139static err_t echo_server_sent(void *arg, struct tcp_pcb *tpcb, u16_t length) 140{ 141 return ERR_OK; 142} 143 144static err_t echo_server_accept(void *arg, struct tcp_pcb *tpcb, err_t err) 145{ 146 assert(err == ERR_OK); 147 tcp_recv(tpcb, echo_server_recv); 148 tcp_sent(tpcb, echo_server_sent); 149 tcp_err(tpcb, echo_server_err); 150 151 tcp_arg(tpcb, 0); 152 153 return ERR_OK; 154} 155 156int tcp_echo_server_init(void) 157{ 158 err_t r; 159 160 uint16_t bind_port = 7; //don't use htons() (don't know why...) 161 162 163 struct tcp_pcb *pcb = tcp_new(); 164 if (pcb == NULL) { 165 return ERR_MEM; 166 } 167 168 r = tcp_bind(pcb, IP_ADDR_ANY, bind_port); 169 if(r != ERR_OK) { 170 return(r); 171 } 172 173 struct tcp_pcb *pcb2 = tcp_listen(pcb); 174 assert(pcb2 != NULL); 175 tcp_accept(pcb2, echo_server_accept); 176 177 178 printf("TCP echo_server_init(): bound.\n"); 179 printf("TCP installed receive callback.\n"); 180 return (0); 181} 182