dfcf3f21db66689cca32782bbf2fec8eb09bc11f
[dpdk.git] / lib / librte_eal / linuxapp / kni / kni_net.c
1 /*-
2  * GPL LICENSE SUMMARY
3  * 
4  *   Copyright(c) 2010-2012 Intel Corporation. All rights reserved.
5  * 
6  *   This program is free software; you can redistribute it and/or modify 
7  *   it under the terms of version 2 of the GNU General Public License as
8  *   published by the Free Software Foundation.
9  * 
10  *   This program is distributed in the hope that it will be useful, but 
11  *   WITHOUT ANY WARRANTY; without even the implied warranty of 
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
13  *   General Public License for more details.
14  * 
15  *   You should have received a copy of the GNU General Public License 
16  *   along with this program; if not, write to the Free Software 
17  *   Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
18  *   The full GNU General Public License is included in this distribution 
19  *   in the file called LICENSE.GPL.
20  * 
21  *   Contact Information:
22  *   Intel Corporation
23  * 
24  */
25
26 /*
27  * This code is inspired from the book "Linux Device Drivers" by
28  * Alessandro Rubini and Jonathan Corbet, published by O'Reilly & Associates
29  */
30
31 #include <linux/device.h>
32 #include <linux/module.h>
33 #include <linux/version.h>
34 #include <linux/netdevice.h>
35 #include <linux/etherdevice.h> /* eth_type_trans */
36 #include <linux/skbuff.h>
37 #include <linux/kthread.h>
38 #include <linux/delay.h>
39
40 #include <rte_config.h>
41 #include <exec-env/rte_kni_common.h>
42 #include "kni_dev.h"
43
44 #define WD_TIMEOUT 5 /*jiffies */
45
46 #define MBUF_BURST_SZ 32
47
48 #define KNI_WAIT_RESPONSE_TIMEOUT 300 /* 3 seconds */
49
50 /* typedef for rx function */
51 typedef void (*kni_net_rx_t)(struct kni_dev *kni);
52
53 static int kni_net_tx(struct sk_buff *skb, struct net_device *dev);
54 static void kni_net_rx_normal(struct kni_dev *kni);
55 static void kni_net_rx_lo_fifo(struct kni_dev *kni);
56 static void kni_net_rx_lo_fifo_skb(struct kni_dev *kni);
57 static int kni_net_process_request(struct kni_dev *kni,
58                         struct rte_kni_request *req);
59
60 /* kni rx function pointer, with default to normal rx */
61 static kni_net_rx_t kni_net_rx_func = kni_net_rx_normal;
62
63
64 /**
65  * Adds num elements into the fifo. Return the number actually written
66  */
67 static inline unsigned
68 kni_fifo_put(struct rte_kni_fifo *fifo, void **data, unsigned num)
69 {
70         unsigned i = 0;
71         unsigned fifo_write = fifo->write;
72         unsigned fifo_read = fifo->read;
73         unsigned new_write = fifo_write;
74
75         for (i = 0; i < num; i++) {
76                 new_write = (new_write + 1) & (fifo->len - 1);
77
78                 if (new_write == fifo_read)
79                         break;
80                 fifo->buffer[fifo_write] = data[i];
81                 fifo_write = new_write;
82         }
83         fifo->write = fifo_write;
84         return i;
85 }
86
87 /**
88  * Get up to num elements from the fifo. Return the number actully read
89  */
90 static inline unsigned
91 kni_fifo_get(struct rte_kni_fifo *fifo, void **data, unsigned num)
92 {
93         unsigned i = 0;
94         unsigned new_read = fifo->read;
95         unsigned fifo_write = fifo->write;
96         for (i = 0; i < num; i++) {
97                 if (new_read == fifo_write)
98                         break;
99
100                 data[i] = fifo->buffer[new_read];
101                 new_read = (new_read + 1) & (fifo->len - 1);
102         }
103         fifo->read = new_read;
104         return i;
105 }
106
107 /**
108  * Get the num of elements in the fifo
109  */
110 static inline unsigned
111 kni_fifo_count(struct rte_kni_fifo *fifo)
112 {
113         return (fifo->len + fifo->write - fifo->read) &( fifo->len - 1);
114 }
115
116 /**
117  * Get the num of available lements in the fifo
118  */
119 static inline unsigned
120 kni_fifo_free_count(struct rte_kni_fifo *fifo)
121 {
122         return (fifo->read - fifo->write - 1) & (fifo->len - 1);
123 }
124
125 /*
126  * Open and close
127  */
128 static int
129 kni_net_open(struct net_device *dev)
130 {
131         int ret;
132         struct rte_kni_request req;
133         struct kni_dev *kni = netdev_priv(dev);
134
135         KNI_DBG("kni_net_open %d\n", kni->idx);
136
137         /*
138          * Assign the hardware address of the board: use "\0KNIx", where
139          * x is KNI index. The first byte is '\0' to avoid being a multicast
140          * address (the first byte of multicast addrs is odd).
141          */
142
143         if (kni->lad_dev)
144                 memcpy(dev->dev_addr, kni->lad_dev->dev_addr, ETH_ALEN);
145         else {
146                 memcpy(dev->dev_addr, "\0KNI0", ETH_ALEN);
147                 dev->dev_addr[ETH_ALEN-1] += kni->idx; /* \0KNI1 */
148         }
149
150         netif_start_queue(dev);
151
152         memset(&req, 0, sizeof(req));
153         req.req_id = RTE_KNI_REQ_CFG_NETWORK_IF;
154
155         /* Setting if_up to non-zero means up */
156         req.if_up = 1;
157         ret = kni_net_process_request(kni, &req);
158
159         return (ret == 0 ? req.result : ret);
160 }
161
162 static int
163 kni_net_release(struct net_device *dev)
164 {
165         int ret;
166         struct rte_kni_request req;
167         struct kni_dev *kni = netdev_priv(dev);
168
169         netif_stop_queue(dev); /* can't transmit any more */
170
171         memset(&req, 0, sizeof(req));
172         req.req_id = RTE_KNI_REQ_CFG_NETWORK_IF;
173
174         /* Setting if_up to 0 means down */
175         req.if_up = 0;
176         ret = kni_net_process_request(kni, &req);
177
178         return (ret == 0 ? req.result : ret);
179 }
180
181 /*
182  * Configuration changes (passed on by ifconfig)
183  */
184 static int
185 kni_net_config(struct net_device *dev, struct ifmap *map)
186 {
187         if (dev->flags & IFF_UP) /* can't act on a running interface */
188                 return -EBUSY;
189
190         /* ignore other fields */
191         return 0;
192 }
193
194 /*
195  * RX: normal working mode
196  */
197 static void
198 kni_net_rx_normal(struct kni_dev *kni)
199 {
200         unsigned ret;
201         uint32_t len;
202         unsigned i, num, num_rq, num_fq;
203         struct rte_kni_mbuf *kva;
204         struct rte_kni_mbuf *va[MBUF_BURST_SZ];
205         void * data_kva;
206
207         struct sk_buff *skb;
208         struct net_device *dev = kni->net_dev;
209
210         /* Get the number of entries in rx_q */
211         num_rq = kni_fifo_count(kni->rx_q);
212
213         /* Get the number of free entries in free_q */
214         num_fq = kni_fifo_free_count(kni->free_q);
215
216         /* Calculate the number of entries to dequeue in rx_q */
217         num = min(num_rq, num_fq);
218         num = min(num, (unsigned)MBUF_BURST_SZ);
219
220         /* Return if no entry in rx_q and no free entry in free_q */
221         if (num == 0)
222                 return;
223
224         /* Burst dequeue from rx_q */
225         ret = kni_fifo_get(kni->rx_q, (void **)va, num);
226         if (ret == 0)
227                 return; /* Failing should not happen */
228
229         /* Transfer received packets to netif */
230         for (i = 0; i < num; i++) {
231                 kva = (void *)va[i] - kni->mbuf_va + kni->mbuf_kva;
232                 len = kva->data_len;
233                 data_kva = kva->data - kni->mbuf_va + kni->mbuf_kva;
234
235                 skb = dev_alloc_skb(len + 2);
236                 if (!skb) {
237                         KNI_ERR("Out of mem, dropping pkts\n");
238                         /* Update statistics */
239                         kni->stats.rx_dropped++;
240                 }
241                 else {
242                         /* Align IP on 16B boundary */
243                         skb_reserve(skb, 2);
244                         memcpy(skb_put(skb, len), data_kva, len);
245                         skb->dev = dev;
246                         skb->protocol = eth_type_trans(skb, dev);
247                         skb->ip_summed = CHECKSUM_UNNECESSARY;
248
249                         /* Call netif interface */
250                         netif_rx(skb);
251
252                         /* Update statistics */
253                         kni->stats.rx_bytes += len;
254                         kni->stats.rx_packets++;
255                 }
256         }
257
258         /* Burst enqueue mbufs into free_q */
259         ret = kni_fifo_put(kni->free_q, (void **)va, num);
260         if (ret != num)
261                 /* Failing should not happen */
262                 KNI_ERR("Fail to enqueue entries into free_q\n");
263 }
264
265 /*
266  * RX: loopback with enqueue/dequeue fifos.
267  */
268 static void
269 kni_net_rx_lo_fifo(struct kni_dev *kni)
270 {
271         unsigned ret;
272         uint32_t len;
273         unsigned i, num, num_rq, num_tq, num_aq, num_fq;
274         struct rte_kni_mbuf *kva;
275         struct rte_kni_mbuf *va[MBUF_BURST_SZ];
276         void * data_kva;
277
278         struct rte_kni_mbuf *alloc_kva;
279         struct rte_kni_mbuf *alloc_va[MBUF_BURST_SZ];
280         void *alloc_data_kva;
281
282         /* Get the number of entries in rx_q */
283         num_rq = kni_fifo_count(kni->rx_q);
284
285         /* Get the number of free entrie in tx_q */
286         num_tq = kni_fifo_free_count(kni->tx_q);
287
288         /* Get the number of entries in alloc_q */
289         num_aq = kni_fifo_count(kni->alloc_q);
290
291         /* Get the number of free entries in free_q */
292         num_fq = kni_fifo_free_count(kni->free_q);
293
294         /* Calculate the number of entries to be dequeued from rx_q */
295         num = min(num_rq, num_tq);
296         num = min(num, num_aq);
297         num = min(num, num_fq);
298         num = min(num, (unsigned)MBUF_BURST_SZ);
299
300         /* Return if no entry to dequeue from rx_q */
301         if (num == 0)
302                 return;
303
304         /* Burst dequeue from rx_q */
305         ret = kni_fifo_get(kni->rx_q, (void **)va, num);
306         if (ret == 0)
307                 return; /* Failing should not happen */
308
309         /* Dequeue entries from alloc_q */
310         ret = kni_fifo_get(kni->alloc_q, (void **)alloc_va, num);
311         if (ret) {
312                 num = ret;
313                 /* Copy mbufs */
314                 for (i = 0; i < num; i++) {
315                         kva = (void *)va[i] - kni->mbuf_va + kni->mbuf_kva;
316                         len = kva->pkt_len;
317                         data_kva = kva->data - kni->mbuf_va +
318                                                 kni->mbuf_kva;
319
320                         alloc_kva = (void *)alloc_va[i] - kni->mbuf_va +
321                                                         kni->mbuf_kva;
322                         alloc_data_kva = alloc_kva->data - kni->mbuf_va +
323                                                                 kni->mbuf_kva;
324                         memcpy(alloc_data_kva, data_kva, len);
325                         alloc_kva->pkt_len = len;
326                         alloc_kva->data_len = len;
327
328                         kni->stats.tx_bytes += len;
329                         kni->stats.rx_bytes += len;
330                 }
331
332                 /* Burst enqueue mbufs into tx_q */
333                 ret = kni_fifo_put(kni->tx_q, (void **)alloc_va, num);
334                 if (ret != num)
335                         /* Failing should not happen */
336                         KNI_ERR("Fail to enqueue mbufs into tx_q\n");
337         }
338
339         /* Burst enqueue mbufs into free_q */
340         ret = kni_fifo_put(kni->free_q, (void **)va, num);
341         if (ret != num)
342                 /* Failing should not happen */
343                 KNI_ERR("Fail to enqueue mbufs into free_q\n");
344
345         /**
346          * Update statistic, and enqueue/dequeue failure is impossible,
347          * as all queues are checked at first.
348          */
349         kni->stats.tx_packets += num;
350         kni->stats.rx_packets += num;
351 }
352
353 /*
354  * RX: loopback with enqueue/dequeue fifos and sk buffer copies.
355  */
356 static void
357 kni_net_rx_lo_fifo_skb(struct kni_dev *kni)
358 {
359         unsigned ret;
360         uint32_t len;
361         unsigned i, num_rq, num_fq, num;
362         struct rte_kni_mbuf *kva;
363         struct rte_kni_mbuf *va[MBUF_BURST_SZ];
364         void * data_kva;
365
366         struct sk_buff *skb;
367         struct net_device *dev = kni->net_dev;
368
369         /* Get the number of entries in rx_q */
370         num_rq = kni_fifo_count(kni->rx_q);
371
372         /* Get the number of free entries in free_q */
373         num_fq = kni_fifo_free_count(kni->free_q);
374
375         /* Calculate the number of entries to dequeue from rx_q */
376         num = min(num_rq, num_fq);
377         num = min(num, (unsigned)MBUF_BURST_SZ);
378
379         /* Return if no entry to dequeue from rx_q */
380         if (num == 0)
381                 return;
382
383         /* Burst dequeue mbufs from rx_q */
384         ret = kni_fifo_get(kni->rx_q, (void **)va, num);
385         if (ret == 0)
386                 return;
387
388         /* Copy mbufs to sk buffer and then call tx interface */
389         for (i = 0; i < num; i++) {
390                 kva = (void *)va[i] - kni->mbuf_va + kni->mbuf_kva;
391                 len = kva->data_len;
392                 data_kva = kva->data - kni->mbuf_va + kni->mbuf_kva;
393
394                 skb = dev_alloc_skb(len + 2);
395                 if (skb == NULL)
396                         KNI_ERR("Out of mem, dropping pkts\n");
397                 else {
398                         /* Align IP on 16B boundary */
399                         skb_reserve(skb, 2);
400                         memcpy(skb_put(skb, len), data_kva, len);
401                         skb->dev = dev;
402                         skb->protocol = eth_type_trans(skb, dev);
403                         skb->ip_summed = CHECKSUM_UNNECESSARY;
404                         dev_kfree_skb(skb);
405                 }
406
407                 /* Simulate real usage, allocate/copy skb twice */
408                 skb = dev_alloc_skb(len + 2);
409                 if (skb == NULL) {
410                         KNI_ERR("Out of mem, dropping pkts\n");
411                         kni->stats.rx_dropped++;
412                 }
413                 else {
414                         /* Align IP on 16B boundary */
415                         skb_reserve(skb, 2);
416                         memcpy(skb_put(skb, len), data_kva, len);
417                         skb->dev = dev;
418                         skb->protocol = eth_type_trans(skb, dev);
419                         skb->ip_summed = CHECKSUM_UNNECESSARY;
420
421                         kni->stats.rx_bytes += len;
422                         kni->stats.rx_packets++;
423
424                         /* call tx interface */
425                         kni_net_tx(skb, dev);
426                 }
427         }
428
429         /* enqueue all the mbufs from rx_q into free_q */
430         ret = kni_fifo_put(kni->free_q, (void **)&va, num);
431         if (ret != num)
432                 /* Failing should not happen */
433                 KNI_ERR("Fail to enqueue mbufs into free_q\n");
434 }
435
436 /* rx interface */
437 void
438 kni_net_rx(struct kni_dev *kni)
439 {
440         /**
441          * It doesn't need to check if it is NULL pointer,
442          * as it has a default value
443          */
444         (*kni_net_rx_func)(kni);
445 }
446
447 /*
448  * Transmit a packet (called by the kernel)
449  */
450 static int
451 kni_net_tx(struct sk_buff *skb, struct net_device *dev)
452 {
453         int len = 0;
454         unsigned ret;
455         struct kni_dev *kni = netdev_priv(dev);
456         struct rte_kni_mbuf *pkt_kva = NULL;
457         struct rte_kni_mbuf *pkt_va = NULL;
458
459         dev->trans_start = jiffies; /* save the timestamp */
460
461         /* Check if the length of skb is less than mbuf size */
462         if (skb->len > kni->mbuf_size)
463                 goto drop;
464
465         /**
466          * Check if it has at least one free entry in tx_q and
467          * one entry in alloc_q.
468          */
469         if (kni_fifo_free_count(kni->tx_q) == 0 ||
470                         kni_fifo_count(kni->alloc_q) == 0) {
471                 /**
472                  * If no free entry in tx_q or no entry in alloc_q,
473                  * drops skb and goes out.
474                  */
475                 goto drop;
476         }
477
478         /* dequeue a mbuf from alloc_q */
479         ret = kni_fifo_get(kni->alloc_q, (void **)&pkt_va, 1);
480         if (likely(ret == 1)) {
481                 void *data_kva;
482
483                 pkt_kva = (void *)pkt_va - kni->mbuf_va + kni->mbuf_kva;
484                 data_kva = pkt_kva->data - kni->mbuf_va + kni->mbuf_kva;
485
486                 len = skb->len;
487                 memcpy(data_kva, skb->data, len);
488                 if (unlikely(len < ETH_ZLEN)) {
489                         memset(data_kva + len, 0, ETH_ZLEN - len);
490                         len = ETH_ZLEN;
491                 }
492                 pkt_kva->pkt_len = len;
493                 pkt_kva->data_len = len;
494
495                 /* enqueue mbuf into tx_q */
496                 ret = kni_fifo_put(kni->tx_q, (void **)&pkt_va, 1);
497                 if (unlikely(ret != 1)) {
498                         /* Failing should not happen */
499                         KNI_ERR("Fail to enqueue mbuf into tx_q\n");
500                         goto drop;
501                 }
502         } else {
503                 /* Failing should not happen */
504                 KNI_ERR("Fail to dequeue mbuf from alloc_q\n");
505                 goto drop;
506         }
507
508         /* Free skb and update statistics */
509         dev_kfree_skb(skb);
510         kni->stats.tx_bytes += len;
511         kni->stats.tx_packets++;
512
513         return NETDEV_TX_OK;
514
515 drop:
516         /* Free skb and update statistics */
517         dev_kfree_skb(skb);
518         kni->stats.tx_dropped++;
519
520         return NETDEV_TX_OK;
521 }
522
523 /*
524  * Deal with a transmit timeout.
525  */
526 static void
527 kni_net_tx_timeout (struct net_device *dev)
528 {
529         struct kni_dev *kni = netdev_priv(dev);
530
531         KNI_DBG("Transmit timeout at %ld, latency %ld\n", jiffies,
532                         jiffies - dev->trans_start);
533
534         kni->stats.tx_errors++;
535         netif_wake_queue(dev);
536         return;
537 }
538
539 /*
540  * Ioctl commands
541  */
542 static int
543 kni_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
544 {
545         struct kni_dev *kni = netdev_priv(dev);
546         KNI_DBG("kni_net_ioctl %d\n", kni->idx);
547
548         return 0;
549 }
550
551 static int
552 kni_net_change_mtu(struct net_device *dev, int new_mtu)
553 {
554         int ret;
555         struct rte_kni_request req;
556         struct kni_dev *kni = netdev_priv(dev);
557
558         KNI_DBG("kni_net_change_mtu new mtu %d to be set\n", new_mtu);
559
560         memset(&req, 0, sizeof(req));
561         req.req_id = RTE_KNI_REQ_CHANGE_MTU;
562         req.new_mtu = new_mtu;
563         ret = kni_net_process_request(kni, &req);
564         if (ret == 0 && req.result == 0)
565                 dev->mtu = new_mtu;
566
567         return (ret == 0 ? req.result : ret);
568 }
569
570 /*
571  * Checks if the user space application provided the resp message
572  */
573 void
574 kni_net_poll_resp(struct kni_dev *kni)
575 {
576         int i = kni_fifo_count(kni->resp_q);
577
578         if (i) {
579                 wake_up_interruptible(&kni->wq);
580         }
581 }
582
583
584 /*
585  * It can be called to process the request.
586  */
587 static int
588 kni_net_process_request(struct kni_dev *kni, struct rte_kni_request *req)
589 {
590         int ret = -1;
591         void *resp_va;
592         unsigned num;
593         int ret_val;
594
595         if (!kni || !req) {
596                 KNI_ERR("No kni instance or request\n");
597                 return -EINVAL;
598         }
599
600         mutex_lock(&kni->sync_lock);
601
602         /* Construct data */
603         memcpy(kni->sync_kva, req, sizeof(struct rte_kni_request));
604         num = kni_fifo_put(kni->req_q, &kni->sync_va, 1);
605         if (num < 1) {
606                 KNI_ERR("Cannot send to req_q\n");
607                 ret = -EBUSY;
608                 goto fail;
609         }
610
611         ret_val = wait_event_interruptible_timeout(kni->wq,
612                         kni_fifo_count(kni->resp_q), 3 * HZ);
613         if (signal_pending(current) || ret_val <= 0) {
614                 ret = -ETIME;
615                 goto fail;
616         }
617         num = kni_fifo_get(kni->resp_q, (void **)&resp_va, 1);
618         if (num != 1 || resp_va != kni->sync_va) {
619                 /* This should never happen */
620                 KNI_ERR("No data in resp_q\n");
621                 ret = -ENODATA;
622                 goto fail;
623         }
624
625
626         memcpy(req, kni->sync_kva, sizeof(struct rte_kni_request));
627         ret = 0;
628
629 fail:
630         mutex_unlock(&kni->sync_lock);
631         return ret;
632 }
633
634 /*
635  * Return statistics to the caller
636  */
637 static struct net_device_stats *
638 kni_net_stats(struct net_device *dev)
639 {
640         struct kni_dev *kni = netdev_priv(dev);
641         return &kni->stats;
642 }
643
644 /*
645  *  Fill the eth header
646  */
647 static int
648 kni_net_header(struct sk_buff *skb, struct net_device *dev,
649                 unsigned short type, const void *daddr,
650                 const void *saddr, unsigned int len)
651 {
652         struct ethhdr *eth = (struct ethhdr *) skb_push(skb, ETH_HLEN);
653
654         memcpy(eth->h_source, saddr ? saddr : dev->dev_addr, dev->addr_len);
655         memcpy(eth->h_dest,   daddr ? daddr : dev->dev_addr, dev->addr_len);
656         eth->h_proto = htons(type);
657
658         return (dev->hard_header_len);
659 }
660
661
662 /*
663  * Re-fill the eth header
664  */
665 static int
666 kni_net_rebuild_header(struct sk_buff *skb)
667 {
668         struct net_device *dev = skb->dev;
669         struct ethhdr *eth = (struct ethhdr *) skb->data;
670
671         memcpy(eth->h_source, dev->dev_addr, dev->addr_len);
672         memcpy(eth->h_dest, dev->dev_addr, dev->addr_len);
673
674         return 0;
675 }
676
677
678 static const struct header_ops kni_net_header_ops = {
679         .create  = kni_net_header,
680         .rebuild = kni_net_rebuild_header,
681         .cache   = NULL,  /* disable caching */
682 };
683
684 static const struct net_device_ops kni_net_netdev_ops = {
685         .ndo_open = kni_net_open,
686         .ndo_stop = kni_net_release,
687         .ndo_set_config = kni_net_config,
688         .ndo_start_xmit = kni_net_tx,
689         .ndo_change_mtu = kni_net_change_mtu,
690         .ndo_do_ioctl = kni_net_ioctl,
691         .ndo_get_stats = kni_net_stats,
692         .ndo_tx_timeout = kni_net_tx_timeout,
693 };
694
695 void
696 kni_net_init(struct net_device *dev)
697 {
698         struct kni_dev *kni = netdev_priv(dev);
699
700         KNI_DBG("kni_net_init\n");
701
702         init_waitqueue_head(&kni->wq);
703         mutex_init(&kni->sync_lock);
704
705         ether_setup(dev); /* assign some of the fields */
706         dev->netdev_ops      = &kni_net_netdev_ops;
707         dev->header_ops      = &kni_net_header_ops;
708         dev->watchdog_timeo = WD_TIMEOUT;
709 }
710
711 void
712 kni_net_config_lo_mode(char *lo_str)
713 {
714         if (!lo_str) {
715                 KNI_PRINT("loopback disabled");
716                 return;
717         }
718
719         if (!strcmp(lo_str, "lo_mode_none"))
720                 KNI_PRINT("loopback disabled");
721         else if (!strcmp(lo_str, "lo_mode_fifo")) {
722                 KNI_PRINT("loopback mode=lo_mode_fifo enabled");
723                 kni_net_rx_func = kni_net_rx_lo_fifo;
724         } else if (!strcmp(lo_str, "lo_mode_fifo_skb")) {
725                 KNI_PRINT("loopback mode=lo_mode_fifo_skb enabled");
726                 kni_net_rx_func = kni_net_rx_lo_fifo_skb;
727         } else
728                 KNI_PRINT("Incognizant parameter, loopback disabled");
729 }
730