| 146 | } |
| 147 | |
| 148 | struct rte_fib * |
| 149 | rte_fib_create(const char *name, int socket_id, struct rte_fib_conf *conf) |
| 150 | { |
| 151 | char mem_name[RTE_FIB_NAMESIZE]; |
| 152 | int ret; |
| 153 | struct rte_fib *fib = NULL; |
| 154 | struct rte_rib *rib = NULL; |
| 155 | struct rte_tailq_entry *te; |
| 156 | struct rte_fib_list *fib_list; |
| 157 | struct rte_rib_conf rib_conf; |
| 158 | |
| 159 | /* Check user arguments. */ |
| 160 | if ((name == NULL) || (conf == NULL) || (conf->max_routes < 0) || |
| 161 | (conf->type > RTE_FIB_DIR24_8)) { |
| 162 | rte_errno = EINVAL; |
| 163 | return NULL; |
| 164 | } |
| 165 | |
| 166 | rib_conf.ext_sz = conf->rib_ext_sz; |
| 167 | rib_conf.max_nodes = conf->max_routes * 2; |
| 168 | |
| 169 | rib = rte_rib_create(name, socket_id, &rib_conf); |
| 170 | if (rib == NULL) { |
| 171 | RTE_LOG(ERR, LPM, |
| 172 | "Can not allocate RIB %s\n", name); |
| 173 | return NULL; |
| 174 | } |
| 175 | |
| 176 | snprintf(mem_name, sizeof(mem_name), "FIB_%s", name); |
| 177 | fib_list = RTE_TAILQ_CAST(rte_fib_tailq.head, rte_fib_list); |
| 178 | |
| 179 | rte_mcfg_tailq_write_lock(); |
| 180 | |
| 181 | /* guarantee there's no existing */ |
| 182 | TAILQ_FOREACH(te, fib_list, next) { |
| 183 | fib = (struct rte_fib *)te->data; |
| 184 | if (strncmp(name, fib->name, RTE_FIB_NAMESIZE) == 0) |
| 185 | break; |
| 186 | } |
| 187 | fib = NULL; |
| 188 | if (te != NULL) { |
| 189 | rte_errno = EEXIST; |
| 190 | goto exit; |
| 191 | } |
| 192 | |
| 193 | /* allocate tailq entry */ |
| 194 | te = rte_zmalloc("FIB_TAILQ_ENTRY", sizeof(*te), 0); |
| 195 | if (te == NULL) { |
| 196 | RTE_LOG(ERR, LPM, |
| 197 | "Can not allocate tailq entry for FIB %s\n", name); |
| 198 | rte_errno = ENOMEM; |
| 199 | goto exit; |
| 200 | } |
| 201 | |
| 202 | /* Allocate memory to store the FIB data structures. */ |
| 203 | fib = rte_zmalloc_socket(mem_name, |
| 204 | sizeof(struct rte_fib), RTE_CACHE_LINE_SIZE, socket_id); |
| 205 | if (fib == NULL) { |