1/**
2 * @file
3 * Modules initialization
4 *
5 */
6
7/*
8 * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without modification,
12 * are permitted provided that the following conditions are met:
13 *
14 * 1. Redistributions of source code must retain the above copyright notice,
15 *    this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright notice,
17 *    this list of conditions and the following disclaimer in the documentation
18 *    and/or other materials provided with the distribution.
19 * 3. The name of the author may not be used to endorse or promote products
20 *    derived from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
23 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
24 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
25 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
27 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
30 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
31 * OF SUCH DAMAGE.
32 *
33 * This file is part of the lwIP TCP/IP stack.
34 *
35 * Author: Adam Dunkels <adam@sics.se>
36 *
37 */
38
39#include "lwip/opt.h"
40
41#include "lwip/init.h"
42#include "lwip/stats.h"
43#include "lwip/sys.h"
44#include "lwip/mem.h"
45#include "lwip/memp.h"
46#include "lwip/pbuf.h"
47#include "lwip/netif.h"
48#include "lwip/sockets.h"
49#include "lwip/ip.h"
50#include "lwip/raw.h"
51#include "lwip/udp.h"
52#include "lwip/tcp.h"
53#include "lwip/snmp_msg.h"
54#include "lwip/autoip.h"
55#include "lwip/igmp.h"
56#include "lwip/dns.h"
57#include "netif/bfeth.h"
58#include "netif/etharp.h"
59
60#include <idc_barrelfish.h>
61#include <mem_barrelfish.h>
62
63#include <barrelfish/barrelfish.h>
64#include <barrelfish/deferred.h>
65#include <barrelfish/net_constants.h>
66#include <netbench/netbench.h>
67
68
69/* FIXME: Move this to config */
70#define MYDEBUGLWIP 1
71
72#ifdef MYDEBUGLWIP
73#define DEBUGPRINTPS(arg...) printf(arg)
74#else
75#define DEBUGPRINTPS(arg...) ((void)0)
76#endif // MYDEBUGLWIP
77
78
79
80
81
82
83
84/* Compile-time sanity checks for configuration errors.
85 * These can be done independently of LWIP_DEBUG, without penalty.
86 */
87#ifndef BYTE_ORDER
88#error "BYTE_ORDER is not defined, you have to define it in your cc.h"
89#endif
90#if (!IP_SOF_BROADCAST && IP_SOF_BROADCAST_RECV)
91#error "If you want to use broadcast filter per pcb on recv operations, you have to define IP_SOF_BROADCAST=1 in your lwipopts.h"
92#endif
93#if (!LWIP_ARP && ARP_QUEUEING)
94#error "If you want to use ARP Queueing, you have to define LWIP_ARP=1 in your lwipopts.h"
95#endif
96#if (!LWIP_UDP && LWIP_UDPLITE)
97#error "If you want to use UDP Lite, you have to define LWIP_UDP=1 in your lwipopts.h"
98#endif
99#if (!LWIP_UDP && LWIP_SNMP)
100#error "If you want to use SNMP, you have to define LWIP_UDP=1 in your lwipopts.h"
101#endif
102#if (!LWIP_UDP && LWIP_DHCP)
103#error "If you want to use DHCP, you have to define LWIP_UDP=1 in your lwipopts.h"
104#endif
105#if (!LWIP_UDP && LWIP_IGMP)
106#error "If you want to use IGMP, you have to define LWIP_UDP=1 in your lwipopts.h"
107#endif
108#if (!LWIP_UDP && LWIP_DNS)
109#error "If you want to use DNS, you have to define LWIP_UDP=1 in your lwipopts.h"
110#endif
111#if (LWIP_ARP && (ARP_TABLE_SIZE > 0x7f))
112#error "If you want to use ARP, ARP_TABLE_SIZE must fit in an s8_t, so, you have to reduce it in your lwipopts.h"
113#endif
114#if (LWIP_ARP && ARP_QUEUEING && (MEMP_NUM_ARP_QUEUE<=0))
115#error "If you want to use ARP Queueing, you have to define MEMP_NUM_ARP_QUEUE>=1 in your lwipopts.h"
116#endif
117#if (LWIP_RAW && (MEMP_NUM_RAW_PCB<=0))
118#error "If you want to use RAW, you have to define MEMP_NUM_RAW_PCB>=1 in your lwipopts.h"
119#endif
120#if (LWIP_UDP && (MEMP_NUM_UDP_PCB<=0))
121#error "If you want to use UDP, you have to define MEMP_NUM_UDP_PCB>=1 in your lwipopts.h"
122#endif
123#if (LWIP_TCP && (MEMP_NUM_TCP_PCB<=0))
124#error "If you want to use TCP, you have to define MEMP_NUM_TCP_PCB>=1 in your lwipopts.h"
125#endif
126#if (LWIP_TCP && (TCP_WND > 0xffff))
127#error "If you want to use TCP, TCP_WND must fit in an u16_t, so, you have to reduce it in your lwipopts.h"
128#endif
129#if (LWIP_TCP && (TCP_SND_QUEUELEN > 0xffff))
130#error "If you want to use TCP, TCP_SND_QUEUELEN must fit in an u16_t, so, you have to reduce it in your lwipopts.h"
131#endif
132#if (LWIP_TCP && ((TCP_MAXRTX > 12) || (TCP_SYNMAXRTX > 12)))
133#error "If you want to use TCP, TCP_MAXRTX and TCP_SYNMAXRTX must less or equal to 12 (due to tcp_backoff table), so, you have to reduce them in your lwipopts.h"
134#endif
135#if (LWIP_TCP && TCP_LISTEN_BACKLOG && (TCP_DEFAULT_LISTEN_BACKLOG < 0) || (TCP_DEFAULT_LISTEN_BACKLOG > 0xff))
136#error "If you want to use TCP backlog, TCP_DEFAULT_LISTEN_BACKLOG must fit into an u8_t"
137#endif
138#if (LWIP_IGMP && (MEMP_NUM_IGMP_GROUP<=1))
139#error "If you want to use IGMP, you have to define MEMP_NUM_IGMP_GROUP>1 in your lwipopts.h"
140#endif
141#if (PPP_SUPPORT && (NO_SYS==1))
142#error "If you want to use PPP, you have to define NO_SYS=0 in your lwipopts.h"
143#endif
144#if (LWIP_NETIF_API && (NO_SYS==1))
145#error "If you want to use NETIF API, you have to define NO_SYS=0 in your lwipopts.h"
146#endif
147#if ((LWIP_SOCKET || LWIP_NETCONN) && (NO_SYS==1))
148#error "If you want to use Sequential API, you have to define NO_SYS=0 in your lwipopts.h"
149#endif
150#if ((LWIP_NETCONN || LWIP_SOCKET) && (MEMP_NUM_TCPIP_MSG_API<=0))
151#error "If you want to use Sequential API, you have to define MEMP_NUM_TCPIP_MSG_API>=1 in your lwipopts.h"
152#endif
153#if (!LWIP_NETCONN && LWIP_SOCKET)
154#error "If you want to use Socket API, you have to define LWIP_NETCONN=1 in your lwipopts.h"
155#endif
156#if (((!LWIP_DHCP) || (!LWIP_AUTOIP)) && LWIP_DHCP_AUTOIP_COOP)
157#error "If you want to use DHCP/AUTOIP cooperation mode, you have to define LWIP_DHCP=1 and LWIP_AUTOIP=1 in your lwipopts.h"
158#endif
159#if (((!LWIP_DHCP) || (!LWIP_ARP)) && DHCP_DOES_ARP_CHECK)
160#error "If you want to use DHCP ARP checking, you have to define LWIP_DHCP=1 and LWIP_ARP=1 in your lwipopts.h"
161#endif
162#if (!LWIP_ARP && LWIP_AUTOIP)
163#error "If you want to use AUTOIP, you have to define LWIP_ARP=1 in your lwipopts.h"
164#endif
165#if (LWIP_SNMP && (SNMP_CONCURRENT_REQUESTS<=0))
166#error "If you want to use SNMP, you have to define SNMP_CONCURRENT_REQUESTS>=1 in your lwipopts.h"
167#endif
168#if (LWIP_SNMP && (SNMP_TRAP_DESTINATIONS<=0))
169#error "If you want to use SNMP, you have to define SNMP_TRAP_DESTINATIONS>=1 in your lwipopts.h"
170#endif
171#if (LWIP_TCP && ((LWIP_EVENT_API && LWIP_CALLBACK_API) || (!LWIP_EVENT_API && !LWIP_CALLBACK_API)))
172#error "One and exactly one of LWIP_EVENT_API and LWIP_CALLBACK_API has to be enabled in your lwipopts.h"
173#endif
174/* There must be sufficient timeouts, taking into account requirements of the subsystems. */
175#if ((NO_SYS==0) && (MEMP_NUM_SYS_TIMEOUT < (LWIP_TCP + IP_REASSEMBLY + LWIP_ARP + (2*LWIP_DHCP) + LWIP_AUTOIP + LWIP_IGMP + LWIP_DNS + PPP_SUPPORT)))
176#error "MEMP_NUM_SYS_TIMEOUT is too low to accomodate all required timeouts"
177#endif
178#if (IP_REASSEMBLY && (MEMP_NUM_REASSDATA > IP_REASS_MAX_PBUFS))
179#error "MEMP_NUM_REASSDATA > IP_REASS_MAX_PBUFS doesn't make sense since each struct ip_reassdata must hold 2 pbufs at least!"
180#endif
181#if (MEM_LIBC_MALLOC && MEM_USE_POOLS)
182#error "MEM_LIBC_MALLOC and MEM_USE_POOLS may not both be simultaneously enabled in your lwipopts.h"
183#endif
184#if (MEM_USE_POOLS && !MEMP_USE_CUSTOM_POOLS)
185#error "MEM_USE_POOLS requires custom pools (MEMP_USE_CUSTOM_POOLS) to be enabled in your lwipopts.h"
186#endif
187
188#if (PBUF_POOL_BUFSIZE <= MEM_ALIGNMENT)
189#error "PBUF_POOL_BUFSIZE must be greater than MEM_ALIGNMENT or the offset may take the full first pbuf"
190#endif
191
192#if (TCP_QUEUE_OOSEQ && !LWIP_TCP)
193#error "TCP_QUEUE_OOSEQ requires LWIP_TCP"
194#endif
195#if (DNS_LOCAL_HOSTLIST && !DNS_LOCAL_HOSTLIST_IS_DYNAMIC && !(defined(DNS_LOCAL_HOSTLIST_INIT)))
196#error "you have to define define DNS_LOCAL_HOSTLIST_INIT {{'host1', 0x123}, {'host2', 0x234}} to initialize DNS_LOCAL_HOSTLIST"
197#endif
198
199
200/* Compile-time checks for deprecated options.
201 */
202#ifdef MEMP_NUM_TCPIP_MSG
203#error "MEMP_NUM_TCPIP_MSG option is deprecated. Remove it from your lwipopts.h."
204#endif
205#ifdef MEMP_NUM_API_MSG
206#error "MEMP_NUM_API_MSG option is deprecated. Remove it from your lwipopts.h."
207#endif
208#ifdef TCP_REXMIT_DEBUG
209#error "TCP_REXMIT_DEBUG option is deprecated. Remove it from your lwipopts.h."
210#endif
211#ifdef RAW_STATS
212#error "RAW_STATS option is deprecated. Remove it from your lwipopts.h."
213#endif
214#ifdef ETHARP_QUEUE_FIRST
215#error "ETHARP_QUEUE_FIRST option is deprecated. Remove it from your lwipopts.h."
216#endif
217#ifdef ETHARP_ALWAYS_INSERT
218#error "ETHARP_ALWAYS_INSERT option is deprecated. Remove it from your lwipopts.h."
219#endif
220#if SO_REUSE
221/* I removed the lot since this was an ugly hack. It broke the raw-API.
222   It also came with many ugly goto's, Christiaan Simons. */
223#error "SO_REUSE currently unavailable, this was a hack"
224#endif
225
226#ifdef LWIP_DEBUG
227static void lwip_sanity_check(void)
228{
229    /* Warnings */
230#if LWIP_NETCONN
231    if (MEMP_NUM_NETCONN >
232        (MEMP_NUM_TCP_PCB + MEMP_NUM_TCP_PCB_LISTEN + MEMP_NUM_UDP_PCB +
233         MEMP_NUM_RAW_PCB))
234        LWIP_PLATFORM_DIAG(("lwip_sanity_check: WARNING: MEMP_NUM_NETCONN should be less than the sum of MEMP_NUM_{TCP,RAW,UDP}_PCB+MEMP_NUM_TCP_PCB_LISTEN\n"));
235#endif                          /* LWIP_NETCONN */
236#if LWIP_TCP
237    if (MEMP_NUM_TCP_SEG < TCP_SND_QUEUELEN)
238        LWIP_PLATFORM_DIAG(("lwip_sanity_check: WARNING: MEMP_NUM_TCP_SEG should be at least as big as TCP_SND_QUEUELEN\n"));
239    if (TCP_SND_QUEUELEN < (2 * (TCP_SND_BUF / TCP_MSS)))
240        LWIP_PLATFORM_DIAG(("lwip_sanity_check: WARNING: TCP_SND_QUEUELEN must be at least as much as (2 * TCP_SND_BUF/TCP_MSS) for things to work\n"));
241    if (TCP_SNDLOWAT > TCP_SND_BUF)
242        LWIP_PLATFORM_DIAG(("lwip_sanity_check: WARNING: TCP_SNDLOWAT must be less than or equal to TCP_SND_BUF.\n"));
243    if (TCP_WND > (PBUF_POOL_SIZE * PBUF_POOL_BUFSIZE))
244        LWIP_PLATFORM_DIAG(("lwip_sanity_check: WARNING: TCP_WND is larger than space provided by PBUF_POOL_SIZE*PBUF_POOL_BUFSIZE\n"));
245
246    if (TCP_WND < TCP_MSS)
247        LWIP_PLATFORM_DIAG(("lwip_sanity_check: WARNING: TCP_WND is smaller than MSS\n"));
248#endif                          /* LWIP_TCP */
249}
250#else                           /* LWIP_DEBUG */
251#define lwip_sanity_check()
252#endif                          /* LWIP_DEBUG */
253
254static int is_ctl = 0;
255struct netbench_details *nb = NULL;
256
257static struct netif netif;
258
259bool is_this_special_app(void)
260{
261    return (is_ctl > 0);
262} // end function: is_this_special_app
263
264static void remaining_lwip_initialization(char *card_name, uint64_t queueid)
265{
266    nb = netbench_alloc("app", RECORDED_EVENTS_COUNT);
267    //asq: connect to the NIC driver, before doing anything else
268    idc_connect_to_driver(card_name, queueid);
269    DEBUGPRINTPS("Connected to driver [%s]\n", card_name);
270    stats_init();
271    sys_init();
272    DEBUGPRINTPS("remaining_lwip_init: allocating pbuf memory\n");
273#ifdef CONFIG_QEMU_NETWORK
274    printf("#### Networking with small amount of memory #####\n");
275#endif // CONFIG_QEMU_NETWORK
276    printf("#### [%u:%"PRIuDOMAINID":%s] [%s] [%d] MEM_SIZE[%d], "
277            "PBUF_POOL_SIZE[%d], MEMP_MAX[%d],  RECEIVE_BUFFERS[%d] qid[%"PRIu64"]####\n",
278       disp_get_core_id(), disp_get_domain_id(), disp_name(),
279       MEM_CONF_LOC, is_ctl, MEM_SIZE, PBUF_POOL_SIZE, MEMP_MAX,
280       RECEIVE_BUFFERS, queueid);
281
282    memp_init();                // 0'st buffer
283
284    DEBUGPRINTPS("remaining_lwip_init: allocating memory for sending\n");
285    mem_init();                 // 1'th buffer
286    DEBUGPRINTPS("remaining_lwip_init: done with memroy allocation\n");
287
288    DEBUGPRINTPS("LWIP: lwip_starting\n");
289    netif_init();
290#if LWIP_SOCKET
291    lwip_socket_init();
292#endif                          /* LWIP_SOCKET */
293    ip_init();
294    DEBUGPRINTPS("r_lwip_init: done ip_init\n");
295#if LWIP_ARP
296    etharp_init();
297#endif                          /* LWIP_ARP */
298#if LWIP_RAW
299    raw_init();
300#endif                          /* LWIP_RAW */
301#if LWIP_UDP
302    udp_init();
303    DEBUGPRINTPS("r_lwip_init: done udp_init\n");
304#endif                          /* LWIP_UDP */
305#if LWIP_TCP
306    tcp_init();
307    DEBUGPRINTPS("r_lwip_init: done tcp_init\n");
308#endif                          /* LWIP_TCP */
309#if LWIP_SNMP
310    snmp_init();
311    DEBUGPRINTPS("r_lwip_init: done snmp_init\n");
312#endif                          /* LWIP_SNMP */
313#if LWIP_AUTOIP
314    autoip_init();
315    DEBUGPRINTPS("r_lwip_init: done autoip_init\n");
316#endif                          /* LWIP_AUTOIP */
317#if LWIP_IGMP
318    igmp_init();
319    DEBUGPRINTPS("r_lwip_init: done igmp_init\n");
320#endif                          /* LWIP_IGMP */
321    DEBUGPRINTPS("r_lwip_init: done2 igmp_init\n");
322#if LWIP_DNS
323    DEBUGPRINTPS("r_lwip_init: starting DNS_init\n");
324    dns_init();
325    DEBUGPRINTPS("r_lwip_init: done DNS_init\n");
326#endif                          /* LWIP_DNS */
327    DEBUGPRINTPS("LWIP: lwip_started\n");
328}
329
330extern struct waitset *lwip_waitset;    // idc_barrelfish.c
331extern struct thread_mutex *lwip_mutex; // idc_barrelfish.c
332
333/**
334 * To be called by the app which wants to perform DHCP on it's own
335 * In current implementation, it is netd.
336 * Perform Sanity check of user-configurable values, and initialize all modules.
337 */
338struct netif *owner_lwip_init(char *card_name, uint64_t queueid)
339{
340    DEBUGPRINTPS("owner_lwip_init: Inside lwip_init\n");
341    is_ctl = 1;
342    lwip_init(card_name, queueid);
343    DEBUGPRINTPS("LWIP: owner_lwip_init: done with connection setup\n");
344    return &netif;
345}
346
347static void call_tcp_tmr(void)
348{
349    lwip_mutex_lock();
350    tcp_tmr();
351    lwip_mutex_unlock();
352}
353
354/**
355 * Perform Sanity check of user-configurable values, and initialize all modules.
356 *
357 * \param card_name Name of service implementing ethernet driver
358 * \param queueid Queueid which is allocated to this application
359 * \param opt_waitset Optional pointer to waitset to be used by LWIP
360 * \param opt_mutex Optional pointer to mutex to protect multi-threaded domains
361 *
362 * \returns True iff init completes
363 */
364bool lwip_init_ex(const char *card_name, uint64_t queueid,
365                  struct waitset *opt_waitset, struct thread_mutex *opt_mutex)
366{
367    printf("lwip_init_ex: starting......................\n");
368    DEBUGPRINTPS("LWIP_other: Inside lwip_init\n");
369    static bool run_once;
370
371    if (run_once) {
372        return false;
373    }
374    run_once = true;
375
376    if (opt_waitset == NULL) {
377        printf("#### %s Going ahead with default wait-set\n", disp_name());
378        lwip_waitset = get_default_waitset();
379    } else {
380        printf("#### %s Going ahead with non-default wait-set\n", disp_name());
381//        lwip_waitset = get_default_waitset();
382        lwip_waitset = opt_waitset;
383    }
384
385    if (opt_mutex != NULL) {
386        lwip_mutex = opt_mutex;
387    }
388
389    /* Sanity check user-configurable values */
390    lwip_sanity_check();
391    DEBUGPRINTPS("LWIP: lwip_init: done with sanity check\n");
392    printf("LWIP: done with sanity check\n");
393    /* Modules initialization */
394    char port_manager_name[MAX_NET_SERVICE_NAME_LEN];
395
396    snprintf(port_manager_name, sizeof(port_manager_name), "%s%s",
397             card_name, NET_PORTS_MNG_SUFFIX);
398
399    // Connecting to the port_manager_service
400    idc_connect_port_manager_service(port_manager_name);
401
402
403    if (is_ctl != 1) {
404        // connecting to ARP lookup service
405        // Doing this before everything else so that we know all needed
406        // services are up and running.
407        char ARP_service_name[MAX_NET_SERVICE_NAME_LEN];
408        snprintf(ARP_service_name, sizeof(ARP_service_name), "%s%s",
409             card_name, NET_ARP_LOOKUP_SUFFIX);
410        idc_connect_ARP_lookup_service(ARP_service_name);
411    }
412
413    DEBUGPRINTPS("LWIP: lwip_init: done with connection setup\n");
414    printf("LWIP: done with connection setup\n");
415    remaining_lwip_initialization((char *) card_name, queueid);
416
417    if (is_ctl != 1) {
418        DEBUGPRINTPS("getting IP from ARP service\n");
419        printf("LWIP: getting IP from ARP service\n");
420        idc_get_ip_from_ARP_lookup();
421    }
422
423    // Register timers... (TCP only)
424    // FIXME: These timers should be added only when first TCP connection
425    // is requested and not when networking is started!!!!
426    static struct periodic_event tcp_timer;
427    errval_t err = periodic_event_create(&tcp_timer, lwip_waitset,
428                                         TCP_TMR_INTERVAL * 1000,
429                                         MKCLOSURE((void (*)(void *))
430                                                   call_tcp_tmr, NULL));
431    assert(err_is_ok(err));
432
433    // FIXME: I am not sure if this should be in the codepath for both
434    // is_ctl and non-is_ctl.  Specially becasuse non is_ctl is anyways
435    // adding one interface with idc_get_ip* call.
436
437    // Bring interface up
438    struct ip_addr ipaddr, netmask, gw;
439
440    ip_addr_set(&ipaddr, IP_ADDR_ANY);
441    ip_addr_set(&netmask, IP_ADDR_ANY);
442    ip_addr_set(&gw, IP_ADDR_ANY);
443    struct netif *n = netif_add(&netif, &ipaddr, &netmask, &gw,
444                                NULL, bfeth_init, ethernet_input);
445
446    assert(n != NULL);
447    extern bool lwip_init_done;
448    lwip_init_done = true;
449
450    printf("lwip_init_ex: done......................\n");
451    return true;
452}
453
454
455/**
456 * Figure out the best NIC card to connect and initialize library network stack.
457 */
458bool lwip_init_auto_ex(struct waitset * opt_waitset,
459                       struct thread_mutex * opt_mutex)
460{
461    char *card_name = NULL;
462    uint64_t default_queueid = 0;
463    /* Figure out the best NIC card that can be used */
464    /* FIXME: hardcoding the NIC card right now, will do smarter detection
465       in future. */
466
467#ifdef CONFIG_QEMU_NETWORK
468    card_name = "rtl8029";
469#else
470    // FIXME: also check for e10k
471    // FIXME: get this from kaluga
472    card_name = "e1000";
473    //card_name = "e10k";
474    //card_name = "vmkitmon_eth";
475#endif // CONFIG_QEMU_NETWORK
476
477    return lwip_init_ex(card_name, default_queueid, opt_waitset, opt_mutex);
478}                               // end function: lwip_init_auto_ex
479
480
481/**
482 *
483 */
484bool lwip_init_auto(void)
485{
486    return lwip_init_auto_ex(NULL, NULL);
487}
488
489/**
490 * Perform Sanity check of user-configurable values, and initialize all modules.
491 */
492bool lwip_init(const char *card_name, uint64_t queueid)
493{
494    if (card_name == NULL) {
495        return lwip_init_auto_ex(NULL, NULL);
496    } else {
497        return lwip_init_ex(card_name, queueid, NULL, NULL);
498    }
499}
500
501
502void lwip_debug_show_spp_status(int connection)
503{
504    debug_show_spp_status(connection);
505}
506
507uint64_t wrapper_perform_lwip_work(void)
508{
509    return perform_lwip_work();
510}
511
512void lwip_benchmark_control(int direction, uint8_t state, uint64_t trigger,
513        uint64_t cl)
514{
515//  printf("calling lwip_benchmark_control\n");
516    //idc_benchmark_control(direction, state, trigger, cl);
517}  // end function: lwip_benchmark_control
518
519uint8_t lwip_driver_benchmark_state(int direction, uint64_t *delta,
520        uint64_t *cl)
521{
522   return get_driver_benchmark_state(direction, delta, cl);
523}
524
525#define FREE_SLOT_THRESHOLD    100
526int is_lwip_loaded(void)
527{
528    // Check for availability of free pbufs
529    if (free_pbuf_pool_count() == 0) {
530        return 1;
531    }
532
533    int slots = lwip_check_sp_capacity(TRANSMIT_CONNECTION);
534    if (slots < FREE_SLOT_THRESHOLD) {
535        return 2;
536    }
537
538    // for receivign connection, one should check if queue is free
539    slots = lwip_check_sp_capacity(RECEIVE_CONNECTION);
540    if (slots < FREE_SLOT_THRESHOLD) {
541//        printf("slots left are %d\n", slots);
542        return 5;
543    }
544
545    // Check load on RX connection
546    slots = idc_check_capacity(RECEIVE_CONNECTION);
547
548    if (slots < FREE_SLOT_THRESHOLD) {
549        return 3;
550    }
551    // Check load on TX connection
552    slots = idc_check_capacity(TRANSMIT_CONNECTION);
553    if (slots < FREE_SLOT_THRESHOLD) {
554        return 4;
555    }
556    // Check for load the driver itself
557    uint64_t tx_slots_left = idc_check_driver_load();
558
559    // Everything is great!
560    return 0;
561}                               // end function: is_lwip_loaded?
562
563
564
565uint64_t lwip_packet_drop_count(void)
566{
567    return idc_get_packet_drop_count();
568}                               // end function: lwip_packet_drop_count
569
570
571// ******************************************************************
572// Functions to assist in benchmarking the network path
573
574
575// Records the time (ts) spent in the event (event_type)
576// Simplified version of netbench_record_event_simple by giving default
577// nbp pointer
578void lwip_record_event_simple(uint8_t event_type, uint64_t ts)
579{
580    netbench_record_event_simple(nb, event_type, ts);
581} // end function: lwip_record_event_simple
582
583void lwip_print_interesting_stats(void)
584{
585
586    netbench_print_event_stat(nb, RPC_CALL_T,  "U: RPC_CALL_T", 1);
587    netbench_print_event_stat(nb, NFS_READCB_T,  "U: NFS_READCB_T", 1);
588    netbench_print_event_stat(nb, NFS_READ_T,  "U: NFS_READ_T", 1);
589    netbench_print_event_stat(nb, NFS_READ_1_T,  "U: NFS_READ_1_T", 1);
590    netbench_print_event_stat(nb, NFS_READ_w_T,  "U: NFS_READ_w_T", 1);
591    /*
592    netbench_print_event_stat(nb, RPC_RECV_T, "U: RPC_RECV_T", 1);
593    netbench_print_event_stat(nb, RPC_CALLBACK_T, "U: RPC_CALLBACK_T", 1);
594    netbench_print_event_stat(nb, RPC_RECV_OUT_T, "U: RPC_RECV_OUT_T", 1);
595    */
596
597/*
598    netbench_print_event_stat(nb, RE_ALL,            "U: RX ALL", 1);
599    netbench_print_event_stat(nb, RX_ALL_PROCESS ,   "U: RX ALL process", 1);
600    netbench_print_event_stat(nb, RE_PBUF_REPLACE,   "U: RX Replace pbuf", 1);
601    netbench_print_event_stat(nb, TX_A_SP_RN_CS, "U: Notification pending", 1);
602*/
603
604/*
605    netbench_print_event_stat(nb, RE_PBUF_REPLACE_1, "U: RX Replace pbuf_1", 1);
606    netbench_print_event_stat(nb, RE_PBUF_REPLACE_2, "U: RX Replace pbuf_2", 1);
607    netbench_print_event_stat(nb, RE_PBUF_REPLACE_3, "U: RX Replace pbuf_3", 1);
608    netbench_print_event_stat(nb, RE_PBUF_QUEUE,     "U: RX RPL PbufQ", 1);
609    netbench_print_event_stat(nb, RE_PKT_RCV_CS,     "U: RX PKT RCV CS", 1);
610*/
611
612/*
613    netbench_print_event_stat(nb, TX_SP,         "U: TX send-pt", 1);
614    netbench_print_event_stat(nb, TX_SP1,        "U: TX send-pt no-noti", 1);
615    netbench_print_event_stat(nb, TX_SPP_FULL,   "U: TX D SPP FUL", 0);
616    netbench_print_event_stat(nb, TX_SN_WAIT,    "U: TX SN WAIT", 1);
617    netbench_print_event_stat(nb, TX_SN_SEND,    "U: TX SN SEND", 1);
618    netbench_print_event_stat(nb, TX_A_SP_RN_CS, "U: TX SP RN CS", 1);
619    netbench_print_event_stat(nb, TX_A_SP_RN_T,  "U: TX SP RN T", 1);
620    netbench_print_event_stat(nb, TX_SND_PKT_S,  "U: TX SND PKT SLOT", 0);
621    netbench_print_event_stat(nb, TX_SND_PKT_C,  "U: TX SND PKTS", 0);
622*/
623
624}
625
626
627// checks and tells if given hardware feature is enabled or not.
628// NOTE: This code is kept in this file because the information about the
629// card name is available here. But we should move into separate file
630// in future.
631bool is_hw_feature_enabled(int hw_feature)
632{
633    // FIXME: based on the cardname and configuration, hardware feature's
634    // activeness should be decided
635    return false;
636} // end function: is_hw_feature_enabled
637