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