1/**
2 * \file net_soft_filters_impl.c
3 * \brief Generic server part responsible for exporting net_soft_filter.if
4 * for most ethernet drivers.  Current drivers using this server code are
5 * -- e1000n
6 * -- rtl8029
7 * -- eMAC
8 *  -- e10k (within shared queue)
9 */
10
11/*
12 * Copyright (c) 2007-11 ETH Zurich.
13 * All rights reserved.
14 *
15 * This file is distributed under the terms in the attached LICENSE file.
16 * If you do not find this file, copies can be found by writing to:
17 * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
18 */
19
20#include <barrelfish/barrelfish.h>
21#include <barrelfish/nameservice_client.h>
22#include <barrelfish/net_constants.h>
23#include <barrelfish/waitset_chan.h>
24
25#include <stdio.h>
26#include <string.h>
27#include <trace/trace.h>
28#include <trace_definitions/trace_defs.h>
29#include <net_queue_manager/net_queue_manager.h>
30#include <bfdmuxvm/vm.h>
31#include <if/net_soft_filters_defs.h>
32#include <if/net_soft_filters_defs.h>
33#include <if/net_queue_manager_defs.h>
34#include "queue_manager_local.h"
35#include "queue_manager_debug.h"
36
37#define RX_RING_MAXMEM 512*1024
38
39#if CONFIG_TRACE && NETWORK_STACK_TRACE
40#define TRACE_ONLY_SUB_NNET 1
41#endif // CONFIG_TRACE && NETWORK_STACK_TRACE
42
43/* This is client_closure for filter management */
44struct client_closure_FM {
45    struct net_soft_filters_binding *app_connection;       /* FIXME: Do I need this? */
46/* FIXME: this should contain the registered buffer ptr */
47};
48
49static errval_t register_filter_memory(struct net_soft_filters_binding *cc,
50                                           struct capref mem_cap, errval_t *rerr);
51static errval_t register_filter(struct net_soft_filters_binding *cc, uint64_t id,
52                            uint64_t len_rx, uint64_t len_tx,
53                            uint64_t buffer_id_rx, uint64_t buffer_id_tx,
54                            uint64_t ftype, uint64_t paused, errval_t *rerr,
55                            uint64_t *filter_id);
56static errval_t register_arp_filter(struct net_soft_filters_binding *cc, uint64_t id,
57                                uint64_t len_rx, uint64_t len_tx, errval_t *rerr);
58static errval_t deregister_filter(struct net_soft_filters_binding *cc,
59                              uint64_t filter_id, errval_t *rerr);
60static errval_t re_register_filter(struct net_soft_filters_binding *cc,
61                               uint64_t filter_id, uint64_t buffer_id_rx,
62                               uint64_t buffer_id_tx, errval_t *rerr);
63static errval_t pause_filter(struct net_soft_filters_binding *cc, uint64_t filter_id,
64                         uint64_t buffer_id_rx, uint64_t buffer_id_tx, errval_t *rerr);
65static errval_t mac_address_request_sf(struct net_soft_filters_binding *cc,
66                                        errval_t *rerr, uint64_t *mac);
67
68// Initialize interface for soft_filters channel
69static struct net_soft_filters_rpc_rx_vtbl rpc_rx_net_soft_filters_vtbl = {
70    .register_filter_memory_call = register_filter_memory,
71    .register_filter_call = register_filter,
72    .re_register_filter_call = re_register_filter,
73    .deregister_filter_call = deregister_filter,
74    .register_arp_filter_call = register_arp_filter,
75    .pause_call = pause_filter,
76    .mac_address_call = mac_address_request_sf,
77};
78
79
80// Measurement purpose, counting interrupt numbers
81uint64_t total_processing_time = 0;
82uint64_t interrupt_counter = 0;
83uint64_t total_rx_p_count = 0;
84uint64_t total_interrupt_time = 0;
85struct client_closure *g_cl = NULL;
86uint64_t total_rx_datasize = 0;
87
88/*****************************************************************
89 * Local states:
90 *****************************************************************/
91
92static char sf_srv_name[MAX_NET_SERVICE_NAME_LEN];
93
94
95// rx ring
96static size_t   rx_ring_size = 0;
97static size_t   rx_ring_bufsz = 0;
98static uint64_t rx_ring_phys = 0;
99static void*    rx_ring_virt = NULL;
100
101// filters state:
102static struct filter *rx_filters;
103static struct filter arp_filter_rx;
104static struct filter arp_filter_tx;
105
106static uint64_t filter_id_counter = 0;
107
108static void export_soft_filters_cb(void *st, errval_t err, iref_t iref)
109{
110    char service_name[MAX_NET_SERVICE_NAME_LEN];
111    struct net_soft_filter_state *state = st;
112
113    snprintf(service_name, sizeof(service_name), "%s%s", sf_srv_name,
114             FILTER_SERVICE_SUFFIX);
115    if (err_is_fail(err)) {
116        DEBUG_ERR(err, "service[%s] export failed", service_name);
117        abort();
118    }
119
120    ETHERSRV_DEBUG("service [%s] exported at iref %u\n", service_name, iref);
121
122    // register this iref with the name service
123    err = nameservice_register(service_name, iref);
124    if (err_is_fail(err)) {
125        DEBUG_ERR(err, "nameservice_register failed for [%s]", service_name);
126        abort();
127    }
128    waitset_chan_trigger(&state->initialization_completed);
129}
130
131static errval_t connect_soft_filters_cb(void *st,
132                                         struct net_soft_filters_binding *b)
133{
134    ETHERSRV_DEBUG("ether_netd service got a connection!55\n");
135
136    // copy my message receive handler vtable to the binding
137    b->rpc_rx_vtbl = rpc_rx_net_soft_filters_vtbl;
138    //b->error_handler = error_handler;
139
140    struct client_closure_FM *ccfm =
141      (struct client_closure_FM *) malloc(sizeof(struct client_closure_FM));
142
143    b->st = ccfm;
144    ccfm->app_connection = b;
145
146    // FIXME: should I refuse more than one connections for FM services?
147    //  Currently, I am accepting them
148
149    // accept the connection (we could return an error to refuse it)
150    return SYS_ERR_OK;
151} // end function: connect_soft_filters_cb
152
153/*****************************************************************
154 *   filter registration
155 *****************************************************************/
156
157static errval_t mac_address_request_sf(struct net_soft_filters_binding *cc,
158    errval_t *err, uint64_t *mac)
159{
160    *err = SYS_ERR_OK;
161    *mac = get_mac_addr_from_device();
162    return SYS_ERR_OK;
163} // end function: mac_address_request_sf
164
165static struct bulk_transfer_slave bt_filter_rx;
166
167static errval_t register_filter_memory(struct net_soft_filters_binding *cc,
168                                           struct capref mem_cap, errval_t *err)
169{
170    *err = SYS_ERR_OK;
171
172    struct frame_identity pa;
173
174    *err = frame_identify(mem_cap, &pa);
175    if(!err_is_ok(*err)) {
176        printf("invoke_frame_identity failed\n");
177        abort();
178    }
179
180    ETHERSRV_DEBUG("register_netd_memory: attempt to register memory\n");
181    // 2 is rx + tx
182    if (pa.bytes < BASE_PAGE_SIZE * 2) {
183        ETHERSRV_DEBUG("netd did not provided enough for filter transfer\n");
184        *err = FILTER_ERR_NOT_ENOUGH_MEMORY;     /* ps: FIXME: enable this error */
185
186    } /* end if: not enough memory */
187    else {                      /* enough memory, try to map it */
188        void *pool;
189
190        *err = vspace_map_one_frame_attr((void *) (&pool), BASE_PAGE_SIZE * 2,
191                                        mem_cap,
192                                        VREGION_FLAGS_READ_WRITE_NOCACHE, NULL,
193                                        NULL);
194
195        if (err_is_fail(*err)) {
196            DEBUG_ERR(*err, "vspace_map_one_frame failed");
197            //            abort();
198        } /* end if: mapping failed */
199        else {
200            // Init receiver
201            *err = bulk_slave_init(pool, BASE_PAGE_SIZE * 2, &bt_filter_rx);
202            //            assert(err_is_ok(err));
203
204        }                       /* end else: mapping sucessful */
205
206    }                           /* end else : */
207    return SYS_ERR_OK;
208} /* end function : register_netd_memory */
209
210/**
211 * \brief: Registers the filter with network driver
212 */
213static errval_t register_filter(struct net_soft_filters_binding *cc, uint64_t id,
214                            uint64_t len_rx, uint64_t len_tx,
215                            uint64_t buffer_id_rx, uint64_t buffer_id_tx,
216                            uint64_t ftype, uint64_t paused, errval_t *err,
217                            uint64_t *filter_id)
218{
219    *err = SYS_ERR_OK;
220
221    struct buffer_descriptor *buffer_rx = NULL;
222    struct buffer_descriptor *buffer_tx = NULL;
223    struct buffer_descriptor *tmp = buffers_list;
224
225    while (tmp) {
226
227        if (tmp->buffer_id == buffer_id_tx) {
228            buffer_tx = tmp;
229        }
230
231        if (tmp->buffer_id == buffer_id_rx) {
232            buffer_rx = tmp;
233        }
234
235        if (buffer_rx != NULL && buffer_tx != NULL) {
236            break;
237        }
238
239        tmp = tmp->next;
240    }                           /* end while : */
241
242    if (buffer_rx == NULL || buffer_tx == NULL) {
243        ETHERSRV_DEBUG("no buffer found for the provided buffer id\n");
244        *err = FILTER_ERR_BUFF_NOT_FOUND;
245        *filter_id = 0;
246        return SYS_ERR_OK;
247    }
248
249    if (len_rx > BASE_PAGE_SIZE) {
250        len_rx = BASE_PAGE_SIZE;
251    }
252
253    if (len_tx > BASE_PAGE_SIZE) {
254        len_tx = BASE_PAGE_SIZE;
255    }
256
257    /* using id to find the location of memory */
258    void *buf = bulk_slave_buf_get_mem(&bt_filter_rx, id, NULL);
259
260    if (buf == NULL) {
261        ETHERSRV_DEBUG("no memory available for filter transfer\n");
262        *err = FILTER_ERR_NO_NETD_MEM;
263        *filter_id = 0;
264        return SYS_ERR_OK;
265    }
266
267    /* Create the filter data-structures */
268    struct filter *new_filter_rx =
269      (struct filter *) malloc(sizeof(struct filter));
270    struct filter *new_filter_tx =
271      (struct filter *) malloc(sizeof(struct filter));
272
273    /* FIXME: use goto to deal with failure conditions and reduce the code */
274    if (new_filter_rx == NULL || new_filter_tx == NULL) {
275        ETHERSRV_DEBUG("out of memory for filter registration\n");
276        *err = ETHERSRV_ERR_NOT_ENOUGH_MEM;
277        *filter_id = 0;
278
279        if (new_filter_rx) {
280            free(new_filter_rx);
281        }
282
283        if (new_filter_tx) {
284            free(new_filter_tx);
285        }
286        return SYS_ERR_OK;
287    }
288
289    /* Zero out the filters */
290    memset(new_filter_rx, 0, sizeof(struct filter));
291    memset(new_filter_tx, 0, sizeof(struct filter));
292
293    /* Allocate memory for holding the filter-data */
294    new_filter_rx->data = (uint8_t *) malloc(len_rx);
295    new_filter_tx->data = (uint8_t *) malloc(len_tx);
296
297    if (new_filter_rx->data == NULL || new_filter_tx->data == NULL) {
298        ETHERSRV_DEBUG("out of memory for filter data registration\n");
299        *err = ETHERSRV_ERR_NOT_ENOUGH_MEM;
300        *filter_id = 0;
301
302        if (new_filter_rx->data) {
303            free(new_filter_rx->data);
304        }
305
306        if (new_filter_tx->data) {
307            free(new_filter_tx->data);
308        }
309
310        free(new_filter_rx);
311        free(new_filter_tx);
312
313        return SYS_ERR_OK;
314    }
315
316    /* Zero-out the area of filter-data */
317    memset(new_filter_rx->data, 0, len_rx);
318    memset(new_filter_tx->data, 0, len_tx);
319
320    filter_id_counter++;
321
322    // rx filter
323    memcpy(new_filter_rx->data, buf, len_rx);
324    new_filter_rx->len = len_rx;
325    new_filter_rx->filter_id = filter_id_counter;
326    new_filter_rx->filter_type = ftype;
327    new_filter_rx->buffer = buffer_rx;
328    new_filter_rx->next = rx_filters;
329    new_filter_rx->paused = paused ? true : false;
330    rx_filters = new_filter_rx;
331    ETHERSRV_DEBUG("filter registered with id %" PRIu64 " and len %d\n",
332                   new_filter_rx->filter_id, new_filter_rx->len);
333
334    // tx filter
335    void *bbuf_tx = buf + BASE_PAGE_SIZE;
336
337    memcpy(new_filter_tx->data, bbuf_tx, len_tx);
338    new_filter_tx->len = len_tx;
339    new_filter_tx->filter_id = filter_id_counter;
340    new_filter_tx->filter_type = ftype;
341    new_filter_tx->buffer = buffer_tx;  // we do not really need to set this
342    /* FIXME: following linked list implementation looks buggy */
343    new_filter_tx->next = buffer_tx->tx_filters;
344    buffer_tx->tx_filters = new_filter_tx;
345    /* FIXME: following looks buggy!!! */
346    buffer_rx->tx_filters = new_filter_tx;      // sometimes rx buffers transmit
347
348    /* reporting back the success/failure */
349    *filter_id = filter_id_counter;
350    return SYS_ERR_OK;
351}                               /* end function: register filter */
352
353static struct filter *delete_from_filter_list(struct filter *head,
354                                              uint64_t filter_id)
355{
356    struct filter *prev = NULL;
357
358    while (head != NULL) {
359        if (head->filter_id == filter_id) {
360            if (prev == NULL) {
361                rx_filters = head->next;
362            } else {
363                prev->next = head->next;
364            }
365            return head;
366        }                       /* end if: filter_id found */
367    }                           /* end while: for each element in list */
368    return NULL;                /* could not not find the id. */
369}
370
371/**
372 * \brief: Deregisters the filter with network driver
373 */
374static errval_t deregister_filter(struct net_soft_filters_binding *cc,
375                              uint64_t filter_id, errval_t *err)
376{
377    *err = SYS_ERR_OK;
378
379    ETHERSRV_DEBUG("DeRegister_filter: ID:%" PRIu64 "\n", filter_id);
380
381    /* Create the filter data-structures */
382    struct filter *rx_filter = NULL;
383    struct filter *tx_filter = NULL;
384
385    rx_filter = delete_from_filter_list(rx_filters, filter_id);
386    /* FIXME: delete the tx_filter from the filter list "buffer_rx->tx_filters" */
387//    tx_filter = delete_from_filter_list(tx_filters, filter_id);
388
389    if (rx_filter == NULL /*|| tx_filter == NULL */ ) {
390        ETHERSRV_DEBUG("Deregister_filter:requested filter_ID [%" PRIu64
391                       "] not found\n", filter_id);
392        *err = FILTER_ERR_FILTER_NOT_FOUND;
393    }
394
395    if (rx_filter) {
396        free(rx_filter);
397    }
398
399    if (tx_filter) {
400        free(tx_filter);
401    }
402
403    /* reporting back the success/failure */
404    ETHERSRV_DEBUG("Deregister_filter: ID %" PRIu64 ": Done\n", filter_id);
405
406    return SYS_ERR_OK;
407}                               /* end function: deregister_filter */
408
409static struct filter *find_from_filter_list(struct filter *head,
410                                            uint64_t filter_id)
411{
412    while (head != NULL) {
413        if (head->filter_id == filter_id) {
414            return head;
415        }                       /* end if: filter_id found */
416        head = head->next;
417    }                           /* end while: for each element in list */
418    return NULL;                /* could not not find the id. */
419}
420
421/**
422 * \brief: re-registers the filter with network driver
423 */
424static errval_t re_register_filter(struct net_soft_filters_binding *cc,
425                               uint64_t filter_id, uint64_t buffer_id_rx,
426                               uint64_t buffer_id_tx, errval_t *err)
427{
428    *err = SYS_ERR_OK;
429
430    ETHERSRV_DEBUG("re_register_filter: ID:%" PRIu64 "\n", filter_id);
431
432    /* Create the filter data-structures */
433    struct filter *rx_filter = NULL;
434
435//    struct filter *tx_filter = NULL;
436
437    rx_filter = find_from_filter_list(rx_filters, filter_id);
438    /* FIXME: delete the tx_filter from the filter list "buffer_rx->tx_filters" */
439//    tx_filter = delete_from_filter_list(tx_filters, filter_id);
440
441    if (rx_filter == NULL /*|| tx_filter == NULL */ ) {
442        ETHERSRV_DEBUG("re_register_filter: requested filter_ID [%" PRIu64
443                       "] not found\n", filter_id);
444        *err = FILTER_ERR_FILTER_NOT_FOUND;
445        return SYS_ERR_OK;
446    }
447
448    /* Find the buffer with given buffer_id */
449    struct buffer_descriptor *buffer_rx = find_buffer(buffer_id_rx);
450    struct buffer_descriptor *buffer_tx = NULL;
451
452    buffer_tx = find_buffer(buffer_id_tx);
453    if (buffer_rx == NULL || buffer_rx == NULL) {
454        ETHERSRV_DEBUG("re_register_filter: provided buffer id's not found\n");
455        ETHERSRV_DEBUG("re_register_filter: rx=[[%" PRIu64 "] = %p], tx=[[%"
456                       PRIu64 "] = %p]\n", buffer_id_rx, buffer_rx,
457                       buffer_id_tx, buffer_tx);
458        *err = FILTER_ERR_BUFFER_NOT_FOUND;      /* set error value */
459        return SYS_ERR_OK;
460    }
461    rx_filter->buffer = buffer_rx;
462    /* FIXME: Also, set the new buffer for tx_filters */
463    /* reporting back the success/failure */
464    ETHERSRV_DEBUG("re_register_filter: ID %" PRIu64 ": Done\n", filter_id);
465
466    return SYS_ERR_OK;
467}                               /* end function: re_register_filter */
468
469/**
470 * \brief: pause the filter with network driver
471 */
472static errval_t pause_filter(struct net_soft_filters_binding *cc, uint64_t filter_id,
473                         uint64_t buffer_id_rx, uint64_t buffer_id_tx, errval_t *err)
474{
475    *err = SYS_ERR_OK;
476
477    ETHERSRV_DEBUG("(un)pause_filter: ID:%" PRIu64 "\n", filter_id);
478
479    /* Create the filter data-structures */
480    struct filter *rx_filter = NULL;
481
482//    struct filter *tx_filter = NULL;
483
484    rx_filter = find_from_filter_list(rx_filters, filter_id);
485    /* FIXME: delete the tx_filter from the filter list "buffer_rx->tx_filters" */
486//    tx_filter = delete_from_filter_list(tx_filters, filter_id);
487
488    if (rx_filter == NULL /*|| tx_filter == NULL */ ) {
489        ETHERSRV_DEBUG("pause_filter: requested filter_ID [%" PRIu64
490                       "] not found\n", filter_id);
491        *err = FILTER_ERR_FILTER_NOT_FOUND;
492        assert(!"NYI");
493        /* wrapper_send_filter_re_register_msg(cc, err, filter_id, */
494        /*         buffer_id_rx, buffer_id_tx); */
495        return SYS_ERR_OK;
496    }
497
498    /* Find the buffer with given buffer_id */
499    struct buffer_descriptor *buffer_rx = find_buffer(buffer_id_rx);
500    struct buffer_descriptor *buffer_tx = NULL;
501
502    buffer_tx = find_buffer(buffer_id_tx);
503    if (buffer_rx == NULL || buffer_rx == NULL) {
504        ETHERSRV_DEBUG("re_register_filter: provided buffer id's not found\n");
505        ETHERSRV_DEBUG("re_register_filter: rx=[[%" PRIu64 "] = %p], tx=[[%"
506                       PRIu64 "] = %p]\n", buffer_id_rx, buffer_rx,
507                       buffer_id_tx, buffer_tx);
508        assert(!"NYI");
509        /* err =  FILTER_ERR_BUFFER_NOT_FOUND; /\* set error value *\/ */
510        /* wrapper_send_filter_re_register_msg(cc, err, filter_id, buffer_id_rx, */
511        /*         buffer_id_tx); */
512    }
513    rx_filter->buffer = buffer_rx;
514    /* FIXME: Also, set the new buffer for tx_filters */
515    /* reporting back the success/failure */
516
517    rx_filter->paused = false;
518    if (rx_filter->pause_bufpos > 0) {
519        for (int i = 0; i < rx_filter->pause_bufpos; i++) {
520            struct bufdesc *bd = &rx_filter->pause_buffer[i];
521
522            struct devq *q = rx_filter->buffer->device_queue;
523            assert(q != NULL);
524            struct client_closure *cl = devq_get_state(q);
525            assert(cl != NULL);
526            copy_packet_to_user(rx_filter->buffer, bd->pkt_data, bd->pkt_len,
527                    bd->flags);
528        }
529    }
530    rx_filter->pause_bufpos = 0;
531
532    ETHERSRV_DEBUG("(un)pause_filter: ID %" PRIu64 ": Done\n", filter_id);
533    return SYS_ERR_OK;
534}                               /* end function: re_register_filter */
535
536static errval_t register_arp_filter(struct net_soft_filters_binding *cc, uint64_t id,
537                                uint64_t len_rx, uint64_t len_tx, errval_t *err)
538{
539    *err = SYS_ERR_OK;
540
541    if (len_rx > BASE_PAGE_SIZE) {
542        len_rx = BASE_PAGE_SIZE;
543    }
544    if (len_tx > BASE_PAGE_SIZE) {
545        len_tx = BASE_PAGE_SIZE;
546    }
547
548    /* using id to find the location of memory */
549    void *buf = bulk_slave_buf_get_mem(&bt_filter_rx, id, NULL);
550
551    if (buf == NULL) {
552        ETHERSRV_DEBUG("no memory available for arp_filter transfer\n");
553        *err = FILTER_ERR_NO_NETD_MEM;
554        return SYS_ERR_OK;
555    }
556
557    arp_filter_rx.data = (uint8_t *) malloc(len_rx);
558    assert(arp_filter_rx.data);
559    memcpy(arp_filter_rx.data, buf, len_rx);
560    arp_filter_rx.len = len_rx;
561    ETHERSRV_DEBUG("#### The received arp RX filter is\n");
562    //    show_binary_blob(arp_filter_rx.data, arp_filter_rx.len);
563
564    void *bbuf_tx = buf + BASE_PAGE_SIZE;
565
566    arp_filter_tx.data = (uint8_t *) malloc(len_tx);
567    assert(arp_filter_tx.data);
568    memcpy(arp_filter_tx.data, bbuf_tx, len_tx);
569    arp_filter_tx.len = len_tx;
570    ETHERSRV_DEBUG("#### The received arp RX filter is\n");
571    //    show_binary_blob(arp_filter_tx.data, arp_filter_tx.len);
572    return SYS_ERR_OK;
573}
574
575static void send_arp_to_all(void *data, uint64_t len, uint64_t flags)
576{
577    struct filter *head = rx_filters;
578
579    ETHERSRV_DEBUG("### Sending the ARP packet to all, %"PRIx64" \n", len);
580    /* sending ARP packets to only those who have registered atleast one
581     * filter with e1000n
582     * */
583
584    /* FIXME: this code will send two copies or ARP if there are two filters
585     * registered, which is incorrect.  Fix it. */
586    struct devq *q = NULL;
587    struct client_closure *cl = NULL;
588    while (head) {
589        q = head->buffer->device_queue;
590        assert(q != NULL);
591        cl = devq_get_state(q);
592        assert(cl != NULL);
593        copy_packet_to_user(head->buffer, data, len, flags);
594        head = head->next;
595    }
596
597    if(waiting_for_netd()){
598    	return;
599    }
600    // Forwarding it to netd as well.
601    struct buffer_descriptor *buffer = ((struct client_closure *)devq_get_state(netd[RECEIVE_CONNECTION]))->buffer_ptr;
602
603
604#if TRACE_ETHERSRV_MODE
605    trace_event(TRACE_SUBSYS_NET, TRACE_EVENT_NET_NI_ARP,
606                (uint32_t) (uintptr_t) data);
607#endif // TRACE_ETHERSRV_MODE
608
609    copy_packet_to_user(buffer, data, len, flags);
610}
611
612struct filter *execute_filters(void *data, size_t len)
613{
614    struct filter *head = rx_filters;
615    int res, error;
616
617    int i = 0;
618
619//      ETHERSRV_DEBUG("Starting the filter matching....\n");
620    // TODO: gracefully handle the error cases, although I think
621    // it is not really necessary. since it could only mean we have
622    // received a corrupted packet.
623    while (head) {
624        res = execute_filter(head->data, head->len, (uint8_t *) data,
625                             len, &error);
626        if (res) {
627            // FIXME IK: we need some way of testing how precise a match is
628            // and take the most precise match (ie with the least wildcards)
629            // Currently we just take the most recently added filter as
630            // reflected by the order in the list.
631            ETHERSRV_DEBUG("##### Filter_id [%" PRIu64 "] type[%" PRIu64
632                           "] matched giving buff [%" PRIu64 "].., len [%" PRIu64 "]\n",
633                           head->filter_id, head->filter_type,
634                           head->buffer->buffer_id, len);
635            return head;
636        }
637        head = head->next;
638        ++i;
639    }
640    return NULL;
641}
642
643/** Return virtual address for RX buffer. */
644static void* rx_ring_buffer(void *opaque)
645{
646    size_t idx = (size_t) opaque;
647
648/*    printf("rx_ring_size %zd, idx %zd rx_ring_bufsz %zd\n",
649            rx_ring_size, idx, rx_ring_bufsz);
650*/
651
652    assert(idx < rx_ring_size);
653
654    return ((void*) ((uintptr_t) rx_ring_virt + idx * rx_ring_bufsz));
655}
656
657/** Register a RX buffer with the driver. */
658static void rx_ring_register_buffer(void *opaque)
659{
660    size_t offset;
661    size_t idx = (size_t) opaque;
662
663    offset = idx * rx_ring_bufsz;
664    rx_register_buffer_fn_ptr(rx_ring_phys + offset,
665        ((void*) ((uintptr_t) rx_ring_virt + offset)), opaque);
666}
667
668static void init_rx_ring(size_t rx_bufsz)
669{
670    struct capref frame;
671    errval_t r;
672    struct frame_identity frameid = { .base = 0, .bytes = 0 };
673    size_t capacity = rx_get_free_slots_fn_ptr();
674    size_t size;
675    size_t i;
676
677    rx_ring_bufsz = rx_bufsz;
678    rx_ring_size = MIN(RX_RING_MAXMEM / rx_bufsz, capacity);
679    ETHERSRV_DEBUG("rx_ring_size %zd %zd\n", rx_ring_size, capacity);
680    // TODO: Should I round up here to page size?
681    size = rx_ring_size * rx_bufsz;
682
683    r = frame_alloc(&frame, size, NULL);
684    if (!err_is_ok(r)) {
685        USER_PANIC("Allocating RX buffers for SW filtering failed!");
686    }
687
688    r = frame_identify(frame, &frameid);
689    if (!err_is_ok(r)) {
690        USER_PANIC("Identifying RX frame for SW filtering failed!");
691    }
692    rx_ring_phys = frameid.base;
693
694    r = vspace_map_one_frame_attr(&rx_ring_virt, size, frame,
695            VREGION_FLAGS_READ_WRITE, NULL, NULL);
696    if (!err_is_ok(r)) {
697        USER_PANIC("Mapping RX frame for SW filtering failed!");
698    }
699    memset(rx_ring_virt, 0, size);
700
701
702    // Add buffers to RX ring
703    for (i = 0; i < rx_ring_size; i++) {
704        rx_ring_register_buffer((void*) i);
705    }
706}
707
708void init_soft_filters_service(struct net_soft_filter_state *state, char *service_name, uint64_t qid,
709                               size_t rx_bufsz)
710{
711    // FIXME: do I need separate sf_srv_name for ether_netd services
712    // exporting ether_netd interface
713
714    // Initialize receive buffers
715    init_rx_ring(rx_bufsz);
716
717    filter_id_counter = 0;
718    snprintf(sf_srv_name, sizeof(sf_srv_name), "%s_%"PRIu64"",
719            service_name, qid);
720    errval_t err = net_soft_filters_export(state, export_soft_filters_cb,
721                               connect_soft_filters_cb, get_default_waitset(),
722                               IDC_EXPORT_FLAGS_DEFAULT);
723    if (err_is_fail(err)) {
724        DEBUG_ERR(err, "ethersrv_netd export failed");
725        abort();
726    }
727
728} // end function: init_soft_filters_service
729
730
731// Checks if packet belongs to specific application and sends to it
732static bool handle_application_packet(void *packet, size_t len, uint64_t flags)
733{
734
735    // executing filters to find the relevant buffer
736    uint64_t ts = rdtsc();
737    struct filter *filter = execute_filters(packet, len);
738
739    if (filter == NULL) {
740        // No matching filter
741        return false;
742    }
743
744
745#if TRACE_ONLY_SUB_NNET
746    trace_event(TRACE_SUBSYS_NNET, TRACE_EVENT_NNET_RXESVAPPFDONE,
747                (uint32_t) ((uintptr_t) packet));
748#endif // TRACE_ONLY_SUB_NNET
749
750
751    // Matching filter found, sending packet to application
752    struct buffer_descriptor *buffer = filter->buffer;
753    struct devq *q = buffer->device_queue;
754    assert(q != NULL);
755    struct client_closure *cl = devq_get_state(q);
756    assert(cl != NULL);
757
758    if (cl->debug_state == 4) {
759//        printf("packet for application arrived!!\n");
760        netbench_record_event_simple(bm, RE_FILTER, ts);
761    }
762
763    if (cl->debug_state == 3) {
764        // Trigger to start the recording the stats
765        ts = rdtsc();
766        cl->start_ts = ts;
767        cl->debug_state = 4;
768        interrupt_counter = 0;
769        total_rx_p_count = 0;
770        total_interrupt_time = 0;
771        total_processing_time = 0;
772        total_rx_datasize = 0;
773        g_cl = cl;
774        trace_event(TRACE_SUBSYS_NNET, TRACE_EVENT_NNET_START, 0);
775    }
776
777    if (filter->paused) {
778        // Packet belongs to paused filter
779        assert(filter->pause_bufpos < MAX_PAUSE_BUFFER);
780        struct bufdesc *bd = &filter->pause_buffer[filter->pause_bufpos++];
781
782//        memcpy_fast(bd->pkt_data, packet, len);
783        bd->pkt_len = len;
784        bd->flags = flags;
785        return true;
786    }
787
788    // Normal case
789    if (cl->debug_state == 4) {
790        ++cl->in_filter_matched;
791    }
792
793#if TRACE_ONLY_SUB_NNET
794    trace_event(TRACE_SUBSYS_NNET, TRACE_EVENT_NNET_RXESVAPPCSTART,
795                (uint32_t) ((uintptr_t) packet));
796#endif // TRACE_ONLY_SUB_NNET
797
798    bool ret = copy_packet_to_user(buffer, packet, len, flags);
799    if (ret) {
800        // Packet delivered to the application buffer
801        if (cl->debug_state == 4) {
802            ++cl->in_filter_matched_p;
803
804/*
805            if ((cl->in_filter_matched_p % 1000 ) == 0 ) {
806                printf("@@@@@@ D: %"PRIu64" packets arrived\n",
807                        cl->in_filter_matched_p);
808            }
809*/
810            netbench_record_event_simple(bm, RE_USEFUL, ts);
811        }
812
813    } else {
814        // Could not deliver the packet to application!
815        if (cl->debug_state == 4) {
816            ++cl->in_filter_matched_f;
817            netbench_record_event_simple(bm, RE_DROPPED, ts);
818        }
819//      printf("A: Copy packet to userspace failed\n");
820    }
821    return true;
822} // end function: handle_application_packet
823
824// Checks if packet is of ARP type
825// If YES, then send it to all
826static bool handle_arp_packet(void *packet, size_t len, uint64_t flags)
827{
828    int error;
829
830    if (arp_filter_rx.data == NULL) {
831        return false;
832    }
833
834    bool res = execute_filter(arp_filter_rx.data, arp_filter_rx.len,
835              (uint8_t *) packet, len, &error);
836
837    if (res) { // we have an arp packet
838//      ETHERSRV_DEBUG("ARP packet...\n");
839        send_arp_to_all(packet, len, flags);
840        return true;
841    }
842
843    return false;
844} // end function: handle_arp_packet
845
846
847// give this packet to netd
848static bool handle_netd_packet(void *packet, size_t len, uint64_t flags)
849{
850    if(waiting_for_netd()){
851//        ETHERSRV_DEBUG("waiting for netd\n");
852    	return false;
853    }
854
855  ETHERSRV_DEBUG("No client wants, giving it to netd\n");
856    struct buffer_descriptor *buffer = ((struct client_closure *)devq_get_state(netd[RECEIVE_CONNECTION]))->buffer_ptr;
857
858//    ETHERSRV_DEBUG("sending packet up.\n");
859    /* copy the packet to userspace */
860    if(buffer == NULL) {
861        printf("netd buffer not present\n");
862        return false;
863    }
864
865    struct devq *q = buffer->device_queue;
866    if(q == NULL) {
867        printf("netd buffer->con not present\n");
868        return false;
869    }
870
871    struct client_closure *cl = devq_get_state(q);
872    assert(cl != NULL);
873    if (copy_packet_to_user(buffer, packet, len, flags) == false) {
874        ETHERSRV_DEBUG("Copy packet to userspace failed\n");
875    }
876    ETHERSRV_DEBUG("packet handled by netd\n");
877    return true;
878} // end function: handle_netd_packet
879
880#if 0 // LOOPBACK
881// give this packet to netd
882static bool handle_loopback_packet(void *packet, size_t len, void *opaque,
883        uint64_t flags)
884{
885
886    ETHERSRV_DEBUG("sending up the loopback packet\n");
887
888    // FIXME: get the receiver buffer
889    struct buffer_descriptor *buffer = get_lo_receiver(opaque);
890
891//    ETHERSRV_DEBUG("sending packet up.\n");
892    /* copy the packet to userspace */
893    if(buffer == NULL) {
894        printf("no loopback receiver found\n");
895        return false;
896    }
897
898    struct net_queue_manager_binding *b = buffer->con;
899    if(b == NULL) {
900        printf("destination buffer->con not present\n");
901        return false;
902    }
903
904    struct client_closure *cl = (struct client_closure *)b->st;
905    assert(cl != NULL);
906    if (copy_packet_to_user(buffer, packet, len, flags) == false) {
907        ETHERSRV_DEBUG("Copy packet to userspace failed\n");
908    }
909    return true;
910} // end function: handle_loopback_packet
911
912
913void sf_process_received_packet_lo(void *opaque_rx, void *opaque_tx,
914        size_t pkt_len, bool is_last, uint64_t flags)
915{
916    void *pkt_data;
917
918    ETHERSRV_DEBUG("pkt_len %zd and rx_ring_bufsz %zd\n", pkt_len,
919            rx_ring_bufsz);
920    assert(pkt_len <= rx_ring_bufsz);
921    // FIXME: allow packets to be distributed over multiple buffers
922    assert(is_last);
923
924    // Get the virtual address for this buffer
925    pkt_data = rx_ring_buffer(opaque_rx);
926
927#if TRACE_ETHERSRV_MODE
928    uint32_t pkt_location = (uint32_t) ((uintptr_t) pkt_data);
929    trace_event(TRACE_SUBSYS_NET, TRACE_EVENT_NET_NI_A, pkt_location);
930#endif // TRACE_ETHERSRV_MODE
931#if TRACE_ONLY_SUB_NNET
932        trace_event(TRACE_SUBSYS_NNET, TRACE_EVENT_NNET_RXESVSEE,
933                    (uint32_t) ((uintptr_t) pkt_data));
934#endif // TRACE_ONLY_SUB_NNET
935
936    if (is_loopback_device) {
937        if(handle_loopback_packet(pkt_data, pkt_len, opaque_tx, flags)) {
938            goto out;
939        } else {
940            USER_PANIC("handle_loopback_packet failed");
941        }
942    }
943
944out:
945     rx_ring_register_buffer(opaque_rx);
946} // end function: sf_process_received_packet_lo
947#endif
948
949
950void sf_process_received_packet(struct driver_rx_buffer *buf, size_t count,
951                                uint64_t flags)
952{
953    void *pkt_data;
954    void *opaque;
955    size_t pkt_len;
956
957    // FIXME: allow packets to be distributed over multiple buffers
958    assert(count == 1);
959
960    opaque = buf[0].opaque;
961    pkt_len = buf[0].len;
962    // Get the virtual address for this buffer
963    pkt_data = rx_ring_buffer(opaque);
964
965    assert(pkt_len <= rx_ring_bufsz);
966
967#if TRACE_ETHERSRV_MODE
968    uint32_t pkt_location = (uint32_t) ((uintptr_t) pkt_data);
969    trace_event(TRACE_SUBSYS_NET, TRACE_EVENT_NET_NI_A, pkt_location);
970#endif // TRACE_ETHERSRV_MODE
971#if TRACE_ONLY_SUB_NNET
972        trace_event(TRACE_SUBSYS_NNET, TRACE_EVENT_NNET_RXESVSEE,
973                    (uint32_t) ((uintptr_t) pkt_data));
974#endif // TRACE_ONLY_SUB_NNET
975
976#if 0  // LOOPBACK
977    if (is_loopback_device) {
978        if(handle_loopback_packet(pkt_data, pkt_len, opaque, flags)) {
979            goto out;
980        } else {
981            USER_PANIC("handle_loopback_packet failed");
982        }
983    }
984#endif
985
986    // check for fragmented packet
987    if (handle_fragmented_packet(pkt_data, pkt_len, flags)) {
988        ETHERSRV_DEBUG("fragmented packet..\n");
989        goto out;
990    }
991
992#if TRACE_ONLY_SUB_NNET
993        trace_event(TRACE_SUBSYS_NNET, TRACE_EVENT_NNET_RXESVFRGDONE,
994                    (uint32_t) ((uintptr_t) pkt_data));
995#endif // TRACE_ONLY_SUB_NNET
996
997    // check for application specific packet
998    if (handle_application_packet(pkt_data, pkt_len, flags)) {
999        ETHERSRV_DEBUG
1000        //printf
1001            ("application specific packet.. len %"PRIu64"\n", pkt_len);
1002        goto out;
1003    }
1004
1005    // check for ARP packet
1006     if (handle_arp_packet(pkt_data, pkt_len, flags)) {
1007        ETHERSRV_DEBUG
1008            ("ARP packet..\n");
1009        goto out;
1010    }
1011
1012    // last resort: send packet to netd
1013
1014    ETHERSRV_DEBUG("orphan packet, goes to netd..\n");
1015    handle_netd_packet(pkt_data, pkt_len, flags);
1016
1017out:
1018     rx_ring_register_buffer(opaque);
1019} // end function: process_received_packet
1020