1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2010-2018 Intel Corporation 3 */ 4 5 #include <stdlib.h> 6 #include <string.h> 7 8 #include <rte_ethdev.h> 9 #include <rte_bus_pci.h> 10 #include <rte_string_fns.h> 11 12 #include "kni.h" 13 #include "mempool.h" 14 #include "link.h" 15 16 static struct kni_list kni_list; 17 18 #ifndef KNI_MAX 19 #define KNI_MAX 16 20 #endif 21 22 int 23 kni_init(void) 24 { 25 TAILQ_INIT(&kni_list); 26 27 #ifdef RTE_LIB_KNI 28 rte_kni_init(KNI_MAX); 29 #endif 30 31 return 0; 32 } 33 34 struct kni * 35 kni_find(const char *name) 36 { 37 struct kni *kni; 38 39 if (name == NULL) 40 return NULL; 41 42 TAILQ_FOREACH(kni, &kni_list, node) 43 if (strcmp(kni->name, name) == 0) 44 return kni; 45 46 return NULL; 47 } 48 49 #ifndef RTE_LIB_KNI 50 51 struct kni * 52 kni_create(const char *name __rte_unused, 53 struct kni_params *params __rte_unused) 54 { 55 return NULL; 56 } 57 58 void 59 kni_handle_request(void) 60 { 61 return; 62 } 63 64 #else 65 66 static int 67 kni_config_network_interface(uint16_t port_id, uint8_t if_up) 68 { 69 int ret = 0; 70 71 if (!rte_eth_dev_is_valid_port(port_id)) 72 return -EINVAL; 73 74 ret = (if_up) ? 75 rte_eth_dev_set_link_up(port_id) : 76 rte_eth_dev_set_link_down(port_id); 77 78 return ret; 79 } 80 81 static int 82 kni_change_mtu(uint16_t port_id, unsigned int new_mtu) 83 { 84 int ret; 85 86 if (!rte_eth_dev_is_valid_port(port_id)) 87 return -EINVAL; 88 89 if (new_mtu > RTE_ETHER_MAX_LEN) 90 return -EINVAL; 91 92 /* Set new MTU */ 93 ret = rte_eth_dev_set_mtu(port_id, new_mtu); 94 if (ret < 0) 95 return ret; 96 97 return 0; 98 } 99 100 struct kni * 101 kni_create(const char *name, struct kni_params *params) 102 { 103 struct rte_eth_dev_info dev_info; 104 struct rte_kni_conf kni_conf; 105 struct rte_kni_ops kni_ops; 106 struct kni *kni; 107 struct mempool *mempool; 108 struct link *link; 109 struct rte_kni *k; 110 const struct rte_pci_device *pci_dev; 111 const struct rte_bus *bus = NULL; 112 int ret; 113 114 /* Check input params */ 115 if ((name == NULL) || 116 kni_find(name) || 117 (params == NULL)) 118 return NULL; 119 120 mempool = mempool_find(params->mempool_name); 121 link = link_find(params->link_name); 122 if ((mempool == NULL) || 123 (link == NULL)) 124 return NULL; 125 126 /* Resource create */ 127 ret = rte_eth_dev_info_get(link->port_id, &dev_info); 128 if (ret != 0) 129 return NULL; 130 131 memset(&kni_conf, 0, sizeof(kni_conf)); 132 strlcpy(kni_conf.name, name, RTE_KNI_NAMESIZE); 133 kni_conf.force_bind = params->force_bind; 134 kni_conf.core_id = params->thread_id; 135 kni_conf.group_id = link->port_id; 136 kni_conf.mbuf_size = mempool->buffer_size; 137 if (dev_info.device) 138 bus = rte_bus_find_by_device(dev_info.device); 139 if (bus && !strcmp(bus->name, "pci")) { 140 pci_dev = RTE_DEV_TO_PCI(dev_info.device); 141 kni_conf.addr = pci_dev->addr; 142 kni_conf.id = pci_dev->id; 143 } 144 145 memset(&kni_ops, 0, sizeof(kni_ops)); 146 kni_ops.port_id = link->port_id; 147 kni_ops.config_network_if = kni_config_network_interface; 148 kni_ops.change_mtu = kni_change_mtu; 149 150 k = rte_kni_alloc(mempool->m, &kni_conf, &kni_ops); 151 if (k == NULL) 152 return NULL; 153 154 /* Node allocation */ 155 kni = calloc(1, sizeof(struct kni)); 156 if (kni == NULL) 157 return NULL; 158 159 /* Node fill in */ 160 strlcpy(kni->name, name, sizeof(kni->name)); 161 kni->k = k; 162 163 /* Node add to list */ 164 TAILQ_INSERT_TAIL(&kni_list, kni, node); 165 166 return kni; 167 } 168 169 void 170 kni_handle_request(void) 171 { 172 struct kni *kni; 173 174 TAILQ_FOREACH(kni, &kni_list, node) 175 rte_kni_handle_request(kni->k); 176 } 177 178 #endif 179