1/** 2 * \file 3 * \brief Communication between LWIP and net_ports deamon 4 * 5 * This code provides interface to commuincate with net_ports for purposes like 6 * opening/closing ports, get IP address, etc 7 */ 8 9/* 10 * Copyright (c) 2007-11 ETH Zurich 11 * All rights reserved. 12 * 13 * This file is distributed under the terms in the attached LICENSE file. 14 * If you do not find this file, copies can be found by writing to: 15 * ETH Zurich D-INFK, Universitaetstrasse 6, CH-8092 Zurich. Attn: Systems Group. 16 */ 17 18#include <barrelfish/barrelfish.h> 19#include <barrelfish/nameservice_client.h> 20#include <net_interfaces/net_interfaces.h> 21#include <trace/trace.h> 22#include <netif/etharp.h> 23#include <netif/bfeth.h> 24#include "lwip/init.h" 25#include <netbench/netbench.h> 26#include <if/net_ports_defs.h> 27#include <if/net_ports_defs.h> 28#include <stdio.h> 29#include <assert.h> 30#include "lwip/barrelfish.h" 31#include "idc_barrelfish.h" 32 33#include "lwip_barrelfish_debug.h" 34 35// Can be used 36#define DISABLE_PORTMNG 1 37 38 39/* 40 * If we are the owner of lwip stack, then we dont need rpc 41 */ 42static bool is_owner = 0; 43static uint16_t(*alloc_tcp_port) (void) = NULL; 44static uint16_t(*alloc_udp_port) (void) = NULL; 45 46static uint16_t(*bind_port) (uint16_t port, net_ports_port_type_t type) = NULL; 47static void (*close_port) (uint16_t port, net_ports_port_type_t type) = NULL; 48 49/************************************************************* 50 * \defGroup LocalStates Local states 51 * 52 * @{ 53 * 54 ****************************************************************/ 55static struct net_ports_binding *net_ports_binding; 56static bool net_ports_service_connected = false; 57 58static net_ports_appid_t appid_delete = 0; 59 60static struct netif netif; 61 62//static struct thread *trace_thread = NULL; 63void thread_debug_regs(struct thread *t); 64 65// Variables shared with idc_barrelfish.c 66extern struct waitset *lwip_waitset; 67extern uint64_t lwip_queue_id; 68 69/** 70 * \brief handle msgs on the tx, rx and then the rest connections in that priority 71 */ 72void network_polling_loop(void) 73{ 74 errval_t err; 75 76 while (1) { 77 err = event_dispatch(lwip_waitset); 78 if (err_is_fail(err)) { 79 DEBUG_ERR(err, "in event_dispatch"); 80 break; 81 } 82#if 0 83 if (trace_thread != NULL) { 84 static int iter = 0; 85 86 iter++; 87 if (iter % 10 == 0) { 88 thread_debug_regs(trace_thread); 89 } 90 } 91#endif 92 } 93} 94 95errval_t lwip_err_to_errval(err_t e) 96{ 97 switch (e) { 98 case ERR_OK: 99 return SYS_ERR_OK; 100 case ERR_MEM: 101 return LWIP_ERR_MEM; 102 case ERR_BUF: 103 return LWIP_ERR_BUF; 104 case ERR_TIMEOUT: 105 return LWIP_ERR_TIMEOUT; 106 case ERR_RTE: 107 return LWIP_ERR_RTE; 108 case ERR_ABRT: 109 return LWIP_ERR_ABRT; 110 case ERR_RST: 111 return LWIP_ERR_RST; 112 case ERR_CLSD: 113 return LWIP_ERR_CLSD; 114 case ERR_CONN: 115 return LWIP_ERR_CONN; 116 case ERR_VAL: 117 return LWIP_ERR_VAL; 118 case ERR_ARG: 119 return LWIP_ERR_ARG; 120 case ERR_USE: 121 return LWIP_ERR_USE; 122 case ERR_IF: 123 return LWIP_ERR_IF; 124 case ERR_ISCONN: 125 return LWIP_ERR_ISCONN; 126 case ERR_INPROGRESS: 127 return LWIP_ERR_INPROGRESS; 128 default: 129 USER_PANIC("unknown LWIP error in lwip_err_to_errval"); 130 } 131} 132 133/*************************************************************** 134 Adding new code to communicate with net_ports server 135*/ 136 137/**************************************************************** 138 * \defGroup net_ports_connectivity Code to connect and work with net_ports. 139 * 140 * @{ 141 * 142 *****************************************************************/ 143/** 144 * \brief Callback function when bind is successful. 145 * Code inspired (ie. copied) from "start_client" function. 146 */ 147static void net_ports_bind_cb(void *st, errval_t err, struct net_ports_binding *b) 148{ 149 if (err_is_fail(err)) { 150 DEBUG_ERR(err, "bind failed for net_ports"); 151 abort(); 152 } 153 LWIPBF_DEBUG("net_ports_bind_cb: called\n"); 154 155 net_ports_binding = b; 156 net_ports_rpc_client_init(net_ports_binding); 157 net_ports_service_connected = true; 158 LWIPBF_DEBUG("net_ports_bind_cb: net_ports bind successful!\n"); 159} 160 161/** 162 * \brief Connects the lwip instance with net_ports daemon. 163 * Code inspired (ie. copied) from "start_client" function. 164 */ 165static void init_net_ports_connection(char *service_name) 166{ 167 LWIPBF_DEBUG("init_net_ports_connection: called\n"); 168 assert(service_name != NULL); 169 LWIPBF_DEBUG("init_net_ports_connection: connecting to [%s]\n", service_name); 170 171 errval_t err; 172 iref_t iref; 173 174 LWIPBF_DEBUG("init_net_ports_connection: resolving driver %s\n", service_name); 175 176 err = nameservice_blocking_lookup(service_name, &iref); 177 if (err_is_fail(err)) { 178 DEBUG_ERR(err, "lwip: could not connect to the net_ports driver.\n" 179 "Terminating.\n"); 180 abort(); 181 } 182 assert(iref != 0); 183 184 LWIPBF_DEBUG("init_net_ports_connection: connecting\n"); 185 186 err = net_ports_bind(iref, net_ports_bind_cb, NULL, lwip_waitset, 187 IDC_BIND_FLAGS_DEFAULT); 188 if (!err_is_ok(err)) { 189 printf("net_ports_bind_cb failed in init\n"); 190 abort(); 191 } 192 193 LWIPBF_DEBUG("init_net_ports_connection: terminated\n"); 194} 195 196 197// Connects to the port manager service 198// Blocking call: returns only when connection is done 199// In case of error, it will panic!! 200void idc_connect_port_manager_service(char *service_name) 201{ 202 //LWIPBF_DEBUG 203 printf("idc_c_port_mng_srv: trying to [%s]\n", service_name); 204 205 /* FIXME: decide if this is the best place to connect with net_ports */ 206 init_net_ports_connection(service_name); 207 208 // XXX: dispatch on default waitset until bound 209 struct waitset *dws = get_default_waitset(); 210 211 while (!net_ports_service_connected) { 212 errval_t err = event_dispatch(dws); 213 214 if (err_is_fail(err)) { 215 USER_PANIC_ERR(err, "in event_dispatch while binding"); 216 } 217 } 218 //LWIPBF_DEBUG 219 printf("idc_c_port_mng_srv: success [%s]\n", service_name); 220} 221 222 223void idc_get_ip(void) 224{ 225 if (is_owner) { 226 assert(!"owner of lwip should never ask for ip through API\n"); 227 abort(); 228 } 229 LWIPBF_DEBUG("On the way of getting IP\n"); 230 231 errval_t err; 232 struct ip_addr ip, gw, nm; 233 234 err = net_ports_binding->rpc_tx_vtbl.get_ip_info(net_ports_binding, &ip.addr, &gw.addr, 235 &nm.addr); 236 if (err_is_fail(err)) { 237 USER_PANIC_ERR(err, "error sending get_ip_info"); 238 } 239 240 LWIPBF_DEBUG("got answer, now setting up things\n"); 241 netif_add(&netif, &ip, &nm, &gw, NULL, bfeth_init, ethernet_input); 242 netif_set_default(&netif); 243 netif_set_up(&netif); 244 245 LWIPBF_DEBUG("client1: owner has the IP address %d.%d.%d.%d\n", 246 ip4_addr1(&netif.ip_addr), ip4_addr2(&netif.ip_addr), 247 ip4_addr3(&netif.ip_addr), ip4_addr4(&netif.ip_addr)); 248} 249 250 251 252/***********************************************************/ 253/************* Port management *******************/ 254 255static err_t idc_close_port(uint16_t port, int port_type) 256{ 257 LWIPBF_DEBUG("idc_close_port: called\n"); 258 if (is_owner) { 259 close_port((uint64_t) port, port_type); 260 return ERR_OK; 261 } 262 263 LWIPBF_DEBUG("idc_close_port: called\n"); 264 265 errval_t err, msgerr; 266 267 err = net_ports_binding->rpc_tx_vtbl.close_port(net_ports_binding, port_type, port, 268 appid_delete, lwip_queue_id, 269 &msgerr); 270 if (err_is_fail(err)) { 271 USER_PANIC_ERR(err, "error sending get_ip_info"); 272 } 273 274 LWIPBF_DEBUG("idc_close_tcp_port: returning\n"); 275 276 if (msgerr == PORT_ERR_IN_USE) { 277 return ERR_USE; 278 } // FIXME: other errors? 279 return ERR_OK; 280} 281 282 283err_t idc_close_udp_port(uint16_t port) 284{ 285 return idc_close_port(port, net_ports_PORT_UDP); 286} 287 288 289err_t idc_close_tcp_port(uint16_t port) 290{ 291 return idc_close_port(port, net_ports_PORT_TCP); 292} 293 294static err_t idc_bind_port(uint16_t port, net_ports_port_type_t port_type) 295{ 296 if (is_owner) { 297 LWIPBF_DEBUG("idc_bind_port: called by owner\n"); 298 return bind_port(port, port_type); 299 } 300 301 LWIPBF_DEBUG("idc_bind_port: called\n"); 302 303 errval_t err, msgerr; 304 305 /* getting the proper buffer id's here */ 306 err = net_ports_binding->rpc_tx_vtbl.bind_port(net_ports_binding, port_type, port, 307 /* buffer for RX */ 308 get_rx_bufferid(), 309 /* buffer for TX */ 310 get_tx_bufferid(), 311 appid_delete, lwip_queue_id, 312 &msgerr); 313 if (err_is_fail(err)) { 314 USER_PANIC_ERR(err, "error sending get_ip_info"); 315 } 316 317 LWIPBF_DEBUG("idc_new_tcp_port: terminated\n"); 318 319 if (msgerr == PORT_ERR_IN_USE) { 320 return ERR_USE; 321 } // FIXME: other errors? 322 return ERR_OK; 323} 324 325 326err_t idc_bind_udp_port(uint16_t port) 327{ 328 return idc_bind_port(port, net_ports_PORT_UDP); 329} 330 331 332err_t idc_bind_tcp_port(uint16_t port) 333{ 334 return idc_bind_port(port, net_ports_PORT_TCP); 335} 336 337static err_t idc_new_port(uint16_t * port_no, net_ports_port_type_t port_type) 338{ 339 /* NOTE: function with same name exists in Kaver's code for reference 340 purpose */ 341 errval_t err, msgerr; 342 343 //printf 344 LWIPBF_DEBUG 345 ("idc_new_port: ################################### called\n"); 346 347 // antoinek: FIXME: Need to figure out how to deal with this 348 //assert(!"NYI"); 349 350 /* getting the proper buffer id's here */ 351 err = net_ports_binding->rpc_tx_vtbl.get_port(net_ports_binding, port_type, 352 /* buffer for RX */ 353 get_rx_bufferid(), 354 /* buffer for TX */ 355 get_tx_bufferid(), 356 appid_delete, lwip_queue_id, 357 &msgerr, port_no); 358 if (err_is_fail(err)) { 359 USER_PANIC_ERR(err, "error sending get_ip_info"); 360 } 361 362 //printf 363 LWIPBF_DEBUG 364 ("idc_new_port: ################################### terminated\n"); 365 return msgerr; 366} 367 368err_t idc_tcp_new_port(uint16_t * port_no) 369{ 370 if (is_owner) { 371 *port_no = alloc_tcp_port(); 372 return SYS_ERR_OK; 373 } 374 375 return idc_new_port(port_no, net_ports_PORT_TCP); 376} 377 378 379err_t idc_udp_new_port(uint16_t * port_no) 380{ 381 if (is_owner) { 382 *port_no = alloc_udp_port(); 383 return SYS_ERR_OK; 384 385 } 386 387 return idc_new_port(port_no, net_ports_PORT_UDP); 388} 389 390 391static err_t idc_redirect(struct ip_addr *local_ip, u16_t local_port, 392 struct ip_addr *remote_ip, u16_t remote_port, 393 net_ports_port_type_t port_type) 394{ 395 if (is_owner) { 396 // redirecting doesn't make sense if we are the owner 397 return ERR_USE; // TODO: correct error 398 } 399 400 errval_t msgerr; 401// errval_t err; 402 403 USER_PANIC("Pause: NYI"); 404 abort(); 405 406#if 0 407 /* getting the proper buffer id's here */ 408 err = 409 net_ports_binding->rpc_tx_vtbl.redirect(net_ports_binding, port_type, local_ip->addr, local_port, 410 remote_ip->addr, remote_port, 411 /* buffer for RX */ 412 get_rx_bufferid(), 413 /* buffer for TX */ 414 get_tx_bufferid(), 415 &msgerr); 416 if (err_is_fail(err)) { 417 USER_PANIC_ERR(err, "error sending redirect"); 418 } 419#endif // 0 420 421 if (msgerr == PORT_ERR_IN_USE) { 422 return ERR_USE; 423 } else if (msgerr == PORT_ERR_REDIRECT) { 424 return ERR_USE; // TODO: correct error 425 } 426// FIXME: other errors? 427 return ERR_OK; 428} 429 430static err_t idc_pause(struct ip_addr *local_ip, u16_t local_port, 431 struct ip_addr *remote_ip, u16_t remote_port, 432 net_ports_port_type_t port_type) 433{ 434 if (is_owner) { 435 // redirecting doesn't make sense if we are the owner 436 return ERR_USE; // TODO: correct error 437 } 438 439 errval_t msgerr; 440// errval_t err; 441 442 USER_PANIC("Pausing not support anymore"); 443 abort(); 444#if 0 445 /* getting the proper buffer id's here */ 446 err = 447 net_ports_binding->rpc_tx_vtbl.redirect_pause(net_ports_binding, port_type, local_ip->addr, 448 local_port, remote_ip->addr, remote_port, 449 /* buffer for RX */ 450 ((struct client_closure_NC *) 451 driver_connection[RECEIVE_CONNECTION]->st)-> 452 buff_ptr->buffer_id, 453 /* buffer for TX */ 454 ((struct client_closure_NC *) 455 driver_connection[TRANSMIT_CONNECTION]-> 456 st)->buff_ptr->buffer_id, &msgerr); 457 if (err_is_fail(err)) { 458 USER_PANIC_ERR(err, "error sending pause"); 459 } 460 461#endif // 0 462 if (msgerr == PORT_ERR_IN_USE) { 463 return ERR_USE; 464 } else if (msgerr == PORT_ERR_REDIRECT) { 465 return ERR_USE; // TODO: correct error 466 } 467// FIXME: other errors? 468 return ERR_OK; 469} 470 471 472/* 473err_t idc_redirect_udp_port(uint16_t port) 474{ 475 return idc_redirect_port(port, net_ports_PORT_UDP); 476} 477*/ 478 479err_t idc_redirect_tcp(struct ip_addr * local_ip, u16_t local_port, 480 struct ip_addr * remote_ip, u16_t remote_port) 481{ 482 return idc_redirect(local_ip, local_port, remote_ip, remote_port, 483 net_ports_PORT_TCP); 484} 485 486err_t idc_pause_tcp(struct ip_addr * local_ip, u16_t local_port, 487 struct ip_addr * remote_ip, u16_t remote_port) 488{ 489 return idc_pause(local_ip, local_port, remote_ip, remote_port, 490 net_ports_PORT_TCP); 491} 492 493 494void perform_ownership_housekeeping(uint16_t(*alloc_tcp_ptr) (void), 495 uint16_t(*alloc_udp_ptr) (void), 496 uint16_t(*bind_port_ptr) (uint16_t, 497 enum net_ports_port_type_t), 498 void (*close_port_ptr) (uint16_t, 499 enum net_ports_port_type_t)) 500{ 501 is_owner = true; 502 alloc_tcp_port = alloc_tcp_ptr; 503 alloc_udp_port = alloc_udp_ptr; 504 bind_port = bind_port_ptr; 505 close_port = close_port_ptr; 506} 507