89e46d5e5a10d679634515409282574bd3336b81
[dpdk.git] / lib / librte_kni / rte_kni.c
1 /*-
2  *   BSD LICENSE
3  * 
4  *   Copyright(c) 2010-2013 Intel Corporation. All rights reserved.
5  *   All rights reserved.
6  * 
7  *   Redistribution and use in source and binary forms, with or without 
8  *   modification, are permitted provided that the following conditions 
9  *   are met:
10  * 
11  *     * Redistributions of source code must retain the above copyright 
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright 
14  *       notice, this list of conditions and the following disclaimer in 
15  *       the documentation and/or other materials provided with the 
16  *       distribution.
17  *     * Neither the name of Intel Corporation nor the names of its 
18  *       contributors may be used to endorse or promote products derived 
19  *       from this software without specific prior written permission.
20  * 
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
25  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  * 
33  */
34
35 #ifndef RTE_EXEC_ENV_LINUXAPP
36 #error "KNI is not supported"
37 #endif
38
39 #include <string.h>
40 #include <fcntl.h>
41 #include <unistd.h>
42 #include <sys/ioctl.h>
43 #include <netinet/in.h>
44 #include <linux/if.h>
45
46 #include <rte_string_fns.h>
47 #include <rte_ethdev.h>
48 #include <rte_malloc.h>
49 #include <rte_log.h>
50 #include <rte_kni.h>
51 #include <rte_memzone.h>
52 #include <exec-env/rte_kni_common.h>
53 #include "rte_kni_fifo.h"
54
55 #define MAX_MBUF_BURST_NUM            32
56
57 /* Maximum number of ring entries */
58 #define KNI_FIFO_COUNT_MAX     1024
59 #define KNI_FIFO_SIZE          (KNI_FIFO_COUNT_MAX * sizeof(void *) + \
60                                         sizeof(struct rte_kni_fifo))
61
62 #define KNI_REQUEST_MBUF_NUM_MAX      32
63
64 #define KNI_MZ_CHECK(mz) do { if (mz) goto fail; } while (0)
65
66 /**
67  * KNI context
68  */
69 struct rte_kni {
70         char name[IFNAMSIZ];                /**< KNI interface name */
71         uint8_t port_id;                    /**< Port id KNI associate with */
72         struct rte_mempool *pktmbuf_pool;   /**< pkt mbuf mempool */
73         unsigned mbuf_size;                 /**< mbuf size */
74
75         struct rte_kni_fifo *tx_q;          /**< TX queue */
76         struct rte_kni_fifo *rx_q;          /**< RX queue */
77         struct rte_kni_fifo *alloc_q;       /**< Allocated mbufs queue */
78         struct rte_kni_fifo *free_q;        /**< To be freed mbufs queue */
79
80         /* For request & response */
81         struct rte_kni_fifo *req_q;         /**< Request queue */
82         struct rte_kni_fifo *resp_q;        /**< Response queue */
83         void * sync_addr;                   /**< Req/Resp Mem address */
84
85         struct rte_kni_ops ops;             /**< operations for request */
86         uint8_t port_in_use : 1;             /**< kni creation flag */
87 };
88
89 enum kni_ops_status {
90         KNI_REQ_NO_REGISTER = 0,
91         KNI_REQ_REGISTERED,
92 };
93
94 static void kni_free_mbufs(struct rte_kni *kni);
95 static void kni_allocate_mbufs(struct rte_kni *kni);
96
97 static volatile int kni_fd = -1;
98
99 static const struct rte_memzone *
100 kni_memzone_reserve(const char *name, size_t len, int socket_id,
101                                                 unsigned flags)
102 {
103         const struct rte_memzone *mz = rte_memzone_lookup(name);
104
105         if (mz == NULL)
106                 mz = rte_memzone_reserve(name, len, socket_id, flags);
107
108         return mz;
109 }
110
111 struct rte_kni *
112 rte_kni_create(uint8_t port_id,
113                 unsigned mbuf_size,
114                 struct rte_mempool *pktmbuf_pool,
115                 struct rte_kni_ops *ops)
116 {
117         int ret;
118         struct rte_kni_device_info dev_info;
119         struct rte_eth_dev_info eth_dev_info;
120         struct rte_kni *ctx;
121         char itf_name[IFNAMSIZ];
122 #define OBJNAMSIZ 32
123         char obj_name[OBJNAMSIZ];
124         char mz_name[RTE_MEMZONE_NAMESIZE];
125         const struct rte_memzone *mz;
126
127         if (port_id >= RTE_MAX_ETHPORTS || pktmbuf_pool == NULL)
128                 return NULL;
129
130         /* Check FD and open once */
131         if (kni_fd < 0) {
132                 kni_fd = open("/dev/" KNI_DEVICE, O_RDWR);
133                 if (kni_fd < 0) {
134                         RTE_LOG(ERR, KNI, "Can not open /dev/%s\n",
135                                                         KNI_DEVICE);
136                         return NULL;
137                 }
138         }
139
140         rte_eth_dev_info_get(port_id, &eth_dev_info);
141         RTE_LOG(INFO, KNI, "pci: %02x:%02x:%02x \t %02x:%02x\n",
142                                         eth_dev_info.pci_dev->addr.bus,
143                                         eth_dev_info.pci_dev->addr.devid,
144                                         eth_dev_info.pci_dev->addr.function,
145                                         eth_dev_info.pci_dev->id.vendor_id,
146                                         eth_dev_info.pci_dev->id.device_id);
147         dev_info.bus = eth_dev_info.pci_dev->addr.bus;
148         dev_info.devid = eth_dev_info.pci_dev->addr.devid;
149         dev_info.function = eth_dev_info.pci_dev->addr.function;
150         dev_info.vendor_id = eth_dev_info.pci_dev->id.vendor_id;
151         dev_info.device_id = eth_dev_info.pci_dev->id.device_id;
152         dev_info.port_id = port_id;
153
154         rte_snprintf(mz_name, RTE_MEMZONE_NAMESIZE, "KNI_INFO_%d", port_id);
155         mz = kni_memzone_reserve(mz_name, sizeof(struct rte_kni), 
156                                 SOCKET_ID_ANY, 0);
157         KNI_MZ_CHECK(mz == NULL);
158         ctx = mz->addr;
159
160         if (ctx->port_in_use != 0) {
161                 RTE_LOG(ERR, KNI, "Port %d has been used\n", port_id);
162                 goto fail;
163         }
164         memset(ctx, 0, sizeof(struct rte_kni));
165         if (ops)
166                 memcpy(&ctx->ops, ops, sizeof(struct rte_kni_ops));
167
168         rte_snprintf(itf_name, IFNAMSIZ, "vEth%u", port_id);
169         rte_snprintf(ctx->name, IFNAMSIZ, itf_name);
170         rte_snprintf(dev_info.name, IFNAMSIZ, itf_name);
171
172         /* TX RING */
173         rte_snprintf(obj_name, OBJNAMSIZ, "kni_tx_%d", port_id);
174         mz = kni_memzone_reserve(obj_name, KNI_FIFO_SIZE, SOCKET_ID_ANY, 0);
175         KNI_MZ_CHECK(mz == NULL);
176         ctx->tx_q = mz->addr;
177         kni_fifo_init(ctx->tx_q, KNI_FIFO_COUNT_MAX);
178         dev_info.tx_phys = mz->phys_addr;
179
180         /* RX RING */
181         rte_snprintf(obj_name, OBJNAMSIZ, "kni_rx_%d", port_id);
182         mz = kni_memzone_reserve(obj_name, KNI_FIFO_SIZE, SOCKET_ID_ANY, 0);
183         KNI_MZ_CHECK(mz == NULL);
184         ctx->rx_q = mz->addr;
185         kni_fifo_init(ctx->rx_q, KNI_FIFO_COUNT_MAX);
186         dev_info.rx_phys = mz->phys_addr;
187
188         /* ALLOC RING */
189         rte_snprintf(obj_name, OBJNAMSIZ, "kni_alloc_%d", port_id);
190         mz = kni_memzone_reserve(obj_name, KNI_FIFO_SIZE, SOCKET_ID_ANY, 0);
191         KNI_MZ_CHECK(mz == NULL);
192         ctx->alloc_q = mz->addr;
193         kni_fifo_init(ctx->alloc_q, KNI_FIFO_COUNT_MAX);
194         dev_info.alloc_phys = mz->phys_addr;
195
196         /* FREE RING */
197         rte_snprintf(obj_name, OBJNAMSIZ, "kni_free_%d", port_id);
198         mz = kni_memzone_reserve(obj_name, KNI_FIFO_SIZE, SOCKET_ID_ANY, 0);
199         KNI_MZ_CHECK(mz == NULL);
200         ctx->free_q = mz->addr;
201         kni_fifo_init(ctx->free_q, KNI_FIFO_COUNT_MAX);
202         dev_info.free_phys = mz->phys_addr;
203
204         /* Request RING */
205         rte_snprintf(obj_name, OBJNAMSIZ, "kni_req_%d", port_id);
206         mz = kni_memzone_reserve(obj_name, KNI_FIFO_SIZE, SOCKET_ID_ANY, 0);
207         KNI_MZ_CHECK(mz == NULL);
208         ctx->req_q = mz->addr;
209         kni_fifo_init(ctx->req_q, KNI_FIFO_COUNT_MAX);
210         dev_info.req_phys = mz->phys_addr;
211
212         /* Response RING */
213         rte_snprintf(obj_name, OBJNAMSIZ, "kni_resp_%d", port_id);
214         mz = kni_memzone_reserve(obj_name, KNI_FIFO_SIZE, SOCKET_ID_ANY, 0);
215         KNI_MZ_CHECK(mz == NULL);
216         ctx->resp_q = mz->addr;
217         kni_fifo_init(ctx->resp_q, KNI_FIFO_COUNT_MAX);
218         dev_info.resp_phys = mz->phys_addr;
219
220         /* Req/Resp sync mem area */
221         rte_snprintf(obj_name, OBJNAMSIZ, "kni_sync_%d", port_id);
222         mz = kni_memzone_reserve(obj_name, KNI_FIFO_SIZE, SOCKET_ID_ANY, 0);
223         KNI_MZ_CHECK(mz == NULL);
224         ctx->sync_addr = mz->addr;
225         dev_info.sync_va = mz->addr;
226         dev_info.sync_phys = mz->phys_addr;
227
228         /* MBUF mempool */
229         rte_snprintf(mz_name, sizeof(mz_name), "MP_%s", pktmbuf_pool->name);
230         mz = rte_memzone_lookup(mz_name);
231         KNI_MZ_CHECK(mz == NULL);
232         dev_info.mbuf_va = mz->addr;
233         dev_info.mbuf_phys = mz->phys_addr;
234         ctx->pktmbuf_pool = pktmbuf_pool;
235         ctx->port_id = port_id;
236         ctx->mbuf_size = mbuf_size;
237
238         /* Configure the buffer size which will be checked in kernel module */
239         dev_info.mbuf_size = ctx->mbuf_size;
240
241         ret = ioctl(kni_fd, RTE_KNI_IOCTL_CREATE, &dev_info);
242         KNI_MZ_CHECK(ret < 0);
243
244         ctx->port_in_use = 1;
245
246         return ctx;
247
248 fail:
249
250         return NULL;
251 }
252
253 static void
254 kni_free_fifo(struct rte_kni_fifo *fifo)
255 {
256         int ret;
257         struct rte_mbuf *pkt;
258
259         do {
260                 ret = kni_fifo_get(fifo, (void **)&pkt, 1);
261                 if (ret)
262                         rte_pktmbuf_free(pkt);
263         } while (ret);
264 }
265
266 int
267 rte_kni_release(struct rte_kni *kni)
268 {
269         if (!kni || kni->port_in_use == 0)
270                 return -1;
271
272         if (ioctl(kni_fd, RTE_KNI_IOCTL_RELEASE, &kni->port_id) < 0) {
273                 RTE_LOG(ERR, KNI, "Fail to release kni device\n");
274                 return -1;
275         }
276
277         /* mbufs in all fifo should be released, except request/response */
278         kni_free_fifo(kni->tx_q);
279         kni_free_fifo(kni->rx_q);
280         kni_free_fifo(kni->alloc_q);
281         kni_free_fifo(kni->free_q);
282         memset(kni, 0, sizeof(struct rte_kni));
283
284         return 0;
285 }
286
287 int
288 rte_kni_handle_request(struct rte_kni *kni)
289 {
290         unsigned ret;
291         struct rte_kni_request *req;
292
293         if (kni == NULL)
294                 return -1;
295
296         /* Get request mbuf */
297         ret = kni_fifo_get(kni->req_q, (void **)&req, 1);
298         if (ret != 1)
299                 return 0; /* It is OK of can not getting the request mbuf */
300
301         if (req != kni->sync_addr) {
302                 rte_panic("Wrong req pointer %p\n", req);
303         }
304
305         /* Analyze the request and call the relevant actions for it */
306         switch (req->req_id) {
307         case RTE_KNI_REQ_CHANGE_MTU: /* Change MTU */
308                 if (kni->ops.change_mtu)
309                         req->result = kni->ops.change_mtu(kni->port_id,
310                                                         req->new_mtu);
311                 break;
312         case RTE_KNI_REQ_CFG_NETWORK_IF: /* Set network interface up/down */
313                 if (kni->ops.config_network_if)
314                         req->result = kni->ops.config_network_if(kni->port_id,
315                                                                 req->if_up);
316                 break;
317         default:
318                 RTE_LOG(ERR, KNI, "Unknown request id %u\n", req->req_id);
319                 req->result = -EINVAL;
320                 break;
321         }
322
323         /* Construct response mbuf and put it back to resp_q */
324         ret = kni_fifo_put(kni->resp_q, (void **)&req, 1);
325         if (ret != 1) {
326                 RTE_LOG(ERR, KNI, "Fail to put the muf back to resp_q\n");
327                 return -1; /* It is an error of can't putting the mbuf back */
328         }
329
330         return 0;
331 }
332
333 unsigned
334 rte_kni_tx_burst(struct rte_kni *kni, struct rte_mbuf **mbufs, unsigned num)
335 {
336         unsigned ret = kni_fifo_put(kni->rx_q, (void **)mbufs, num);
337
338         /* Get mbufs from free_q and then free them */
339         kni_free_mbufs(kni);
340
341         return ret;
342 }
343
344 unsigned
345 rte_kni_rx_burst(struct rte_kni *kni, struct rte_mbuf **mbufs, unsigned num)
346 {
347         unsigned ret = kni_fifo_get(kni->tx_q, (void **)mbufs, num);
348
349         /* Allocate mbufs and then put them into alloc_q */
350         kni_allocate_mbufs(kni);
351
352         return ret;
353 }
354
355 static void
356 kni_free_mbufs(struct rte_kni *kni)
357 {
358         int i, ret;
359         struct rte_mbuf *pkts[MAX_MBUF_BURST_NUM];
360
361         ret = kni_fifo_get(kni->free_q, (void **)pkts, MAX_MBUF_BURST_NUM);
362         if (likely(ret > 0)) {
363                 for (i = 0; i < ret; i++)
364                         rte_pktmbuf_free(pkts[i]);
365         }
366 }
367
368 static void
369 kni_allocate_mbufs(struct rte_kni *kni)
370 {
371         int i, ret;
372         struct rte_mbuf *pkts[MAX_MBUF_BURST_NUM];
373
374         /* Check if pktmbuf pool has been configured */
375         if (kni->pktmbuf_pool == NULL) {
376                 RTE_LOG(ERR, KNI, "No valid mempool for allocating mbufs\n");
377                 return;
378         }
379
380         for (i = 0; i < MAX_MBUF_BURST_NUM; i++) {
381                 pkts[i] = rte_pktmbuf_alloc(kni->pktmbuf_pool);
382                 if (unlikely(pkts[i] == NULL)) {
383                         /* Out of memory */
384                         RTE_LOG(ERR, KNI, "Out of memory\n");
385                         break;
386                 }
387         }
388
389         /* No pkt mbuf alocated */
390         if (i <= 0)
391                 return;
392
393         ret = kni_fifo_put(kni->alloc_q, (void **)pkts, i);
394
395         /* Check if any mbufs not put into alloc_q, and then free them */
396         if (ret >= 0 && ret < i && ret < MAX_MBUF_BURST_NUM) {
397                 int j;
398
399                 for (j = ret; j < i; j++)
400                         rte_pktmbuf_free(pkts[j]);
401         }
402 }
403
404 uint8_t
405 rte_kni_get_port_id(struct rte_kni *kni)
406 {
407         if (kni == NULL)
408                 return ~0x0;
409
410         return kni->port_id;
411 }
412
413 struct rte_kni *
414 rte_kni_info_get(uint8_t port_id)
415 {
416         struct rte_kni *kni;
417         const struct rte_memzone *mz;
418         char mz_name[RTE_MEMZONE_NAMESIZE];
419
420         if(port_id >= RTE_MAX_ETHPORTS) 
421                 return NULL;
422
423         rte_snprintf(mz_name, RTE_MEMZONE_NAMESIZE, "KNI_INFO_%d", port_id);
424         mz = rte_memzone_lookup(mz_name);
425         if (NULL == mz)
426                 return NULL;
427
428         kni = mz->addr;
429         if (0 == kni->port_in_use)
430                 return NULL;
431         
432         return kni;
433 }
434
435 static enum kni_ops_status
436 kni_check_request_register(struct rte_kni_ops *ops)
437 {
438         /* check if KNI request ops has been registered*/
439         if( NULL == ops )
440                 return KNI_REQ_NO_REGISTER;
441                  
442         if((NULL == ops->change_mtu) && (NULL == ops->config_network_if))
443                 return KNI_REQ_NO_REGISTER;
444
445         return KNI_REQ_REGISTERED;
446 }
447
448 int
449 rte_kni_register_handlers(struct rte_kni *kni,struct rte_kni_ops *ops)
450 {
451         enum kni_ops_status req_status;
452         
453         if (NULL == ops) {
454                 RTE_LOG(ERR, KNI, "Invalid KNI request operation.\n");
455                 return -1;
456         }
457
458         if (NULL == kni) {
459                 RTE_LOG(ERR, KNI, "Invalid kni info.\n");
460                 return -1;
461         }
462
463         req_status = kni_check_request_register(&kni->ops);
464         if ( KNI_REQ_REGISTERED == req_status) {
465                 RTE_LOG(ERR, KNI, "The KNI request operation"
466                                         "has already registered.\n");
467                 return -1;
468         }
469
470         memcpy(&kni->ops, ops, sizeof(struct rte_kni_ops));     
471         return 0;
472 }
473
474 int
475 rte_kni_unregister_handlers(struct rte_kni *kni)
476 {
477         if (NULL == kni) {
478                 RTE_LOG(ERR, KNI, "Invalid kni info.\n");
479                 return -1;
480         }
481         
482         if (NULL == &kni->ops) {
483                 RTE_LOG(ERR, KNI, "The invalid  KNI unregister operation.\n");
484                 return -1;
485         }
486         
487         kni->ops.change_mtu = NULL;
488         kni->ops.config_network_if = NULL;
489         return 0;
490 }