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_common.h> 9 #include <rte_byteorder.h> 10 #include <rte_malloc.h> 11 #include <rte_memcpy.h> 12 13 #include "rte_port_in_action.h" 14 15 /** 16 * RTE_PORT_IN_ACTION_FLTR 17 */ 18 static int 19 fltr_cfg_check(struct rte_port_in_action_fltr_config *cfg) 20 { 21 if (cfg == NULL) 22 return -1; 23 24 return 0; 25 } 26 27 struct fltr_data { 28 uint32_t port_id; 29 }; 30 31 static void 32 fltr_init(struct fltr_data *data, 33 struct rte_port_in_action_fltr_config *cfg) 34 { 35 data->port_id = cfg->port_id; 36 } 37 38 static int 39 fltr_apply(struct fltr_data *data, 40 struct rte_port_in_action_fltr_params *p) 41 { 42 /* Check input arguments */ 43 if (p == NULL) 44 return -1; 45 46 data->port_id = p->port_id; 47 48 return 0; 49 } 50 51 /** 52 * RTE_PORT_IN_ACTION_LB 53 */ 54 static int 55 lb_cfg_check(struct rte_port_in_action_lb_config *cfg) 56 { 57 if ((cfg == NULL) || 58 (cfg->key_size < RTE_PORT_IN_ACTION_LB_KEY_SIZE_MIN) || 59 (cfg->key_size > RTE_PORT_IN_ACTION_LB_KEY_SIZE_MAX) || 60 (!rte_is_power_of_2(cfg->key_size)) || 61 (cfg->f_hash == NULL)) 62 return -1; 63 64 return 0; 65 } 66 67 struct lb_data { 68 uint32_t port_id[RTE_PORT_IN_ACTION_LB_TABLE_SIZE]; 69 }; 70 71 static void 72 lb_init(struct lb_data *data, 73 struct rte_port_in_action_lb_config *cfg) 74 { 75 memcpy(data->port_id, cfg->port_id, sizeof(cfg->port_id)); 76 } 77 78 static int 79 lb_apply(struct lb_data *data, 80 struct rte_port_in_action_lb_params *p) 81 { 82 /* Check input arguments */ 83 if (p == NULL) 84 return -1; 85 86 memcpy(data->port_id, p->port_id, sizeof(p->port_id)); 87 88 return 0; 89 } 90 91 /** 92 * Action profile 93 */ 94 static int 95 action_valid(enum rte_port_in_action_type action) 96 { 97 switch (action) { 98 case RTE_PORT_IN_ACTION_FLTR: 99 case RTE_PORT_IN_ACTION_LB: 100 return 1; 101 default: 102 return 0; 103 } 104 } 105 106 #define RTE_PORT_IN_ACTION_MAX 64 107 108 struct ap_config { 109 uint64_t action_mask; 110 struct rte_port_in_action_fltr_config fltr; 111 struct rte_port_in_action_lb_config lb; 112 }; 113 114 static size_t 115 action_cfg_size(enum rte_port_in_action_type action) 116 { 117 switch (action) { 118 case RTE_PORT_IN_ACTION_FLTR: 119 return sizeof(struct rte_port_in_action_fltr_config); 120 case RTE_PORT_IN_ACTION_LB: 121 return sizeof(struct rte_port_in_action_lb_config); 122 default: 123 return 0; 124 } 125 } 126 127 static void* 128 action_cfg_get(struct ap_config *ap_config, 129 enum rte_port_in_action_type type) 130 { 131 switch (type) { 132 case RTE_PORT_IN_ACTION_FLTR: 133 return &ap_config->fltr; 134 135 case RTE_PORT_IN_ACTION_LB: 136 return &ap_config->lb; 137 138 default: 139 return NULL; 140 } 141 } 142 143 static void 144 action_cfg_set(struct ap_config *ap_config, 145 enum rte_port_in_action_type type, 146 void *action_cfg) 147 { 148 void *dst = action_cfg_get(ap_config, type); 149 150 if (dst) 151 memcpy(dst, action_cfg, action_cfg_size(type)); 152 153 ap_config->action_mask |= 1LLU << type; 154 } 155 156 struct ap_data { 157 size_t offset[RTE_PORT_IN_ACTION_MAX]; 158 size_t total_size; 159 }; 160 161 static size_t 162 action_data_size(enum rte_port_in_action_type action, 163 struct ap_config *ap_config __rte_unused) 164 { 165 switch (action) { 166 case RTE_PORT_IN_ACTION_FLTR: 167 return sizeof(struct fltr_data); 168 169 case RTE_PORT_IN_ACTION_LB: 170 return sizeof(struct lb_data); 171 172 default: 173 return 0; 174 } 175 } 176 177 static void 178 action_data_offset_set(struct ap_data *ap_data, 179 struct ap_config *ap_config) 180 { 181 uint64_t action_mask = ap_config->action_mask; 182 size_t offset; 183 uint32_t action; 184 185 memset(ap_data->offset, 0, sizeof(ap_data->offset)); 186 187 offset = 0; 188 for (action = 0; action < RTE_PORT_IN_ACTION_MAX; action++) 189 if (action_mask & (1LLU << action)) { 190 ap_data->offset[action] = offset; 191 offset += action_data_size((enum rte_port_in_action_type)action, 192 ap_config); 193 } 194 195 ap_data->total_size = offset; 196 } 197 198 struct rte_port_in_action_profile { 199 struct ap_config cfg; 200 struct ap_data data; 201 int frozen; 202 }; 203 204 struct rte_port_in_action_profile * 205 rte_port_in_action_profile_create(uint32_t socket_id) 206 { 207 struct rte_port_in_action_profile *ap; 208 209 /* Memory allocation */ 210 ap = rte_zmalloc_socket(NULL, 211 sizeof(struct rte_port_in_action_profile), 212 RTE_CACHE_LINE_SIZE, 213 socket_id); 214 if (ap == NULL) 215 return NULL; 216 217 return ap; 218 } 219 220 int 221 rte_port_in_action_profile_action_register(struct rte_port_in_action_profile *profile, 222 enum rte_port_in_action_type type, 223 void *action_config) 224 { 225 int status; 226 227 /* Check input arguments */ 228 if ((profile == NULL) || 229 profile->frozen || 230 (action_valid(type) == 0) || 231 (profile->cfg.action_mask & (1LLU << type)) || 232 ((action_cfg_size(type) == 0) && action_config) || 233 (action_cfg_size(type) && (action_config == NULL))) 234 return -EINVAL; 235 236 switch (type) { 237 case RTE_PORT_IN_ACTION_FLTR: 238 status = fltr_cfg_check(action_config); 239 break; 240 241 case RTE_PORT_IN_ACTION_LB: 242 status = lb_cfg_check(action_config); 243 break; 244 245 default: 246 status = 0; 247 break; 248 } 249 250 if (status) 251 return status; 252 253 /* Action enable */ 254 action_cfg_set(&profile->cfg, type, action_config); 255 256 return 0; 257 } 258 259 int 260 rte_port_in_action_profile_freeze(struct rte_port_in_action_profile *profile) 261 { 262 if (profile->frozen) 263 return -EBUSY; 264 265 action_data_offset_set(&profile->data, &profile->cfg); 266 profile->frozen = 1; 267 268 return 0; 269 } 270 271 int 272 rte_port_in_action_profile_free(struct rte_port_in_action_profile *profile) 273 { 274 if (profile == NULL) 275 return 0; 276 277 free(profile); 278 return 0; 279 } 280 281 /** 282 * Action 283 */ 284 struct rte_port_in_action { 285 struct ap_config cfg; 286 struct ap_data data; 287 uint8_t memory[0] __rte_cache_aligned; 288 }; 289 290 static __rte_always_inline void * 291 action_data_get(struct rte_port_in_action *action, 292 enum rte_port_in_action_type type) 293 { 294 size_t offset = action->data.offset[type]; 295 296 return &action->memory[offset]; 297 } 298 299 static void 300 action_data_init(struct rte_port_in_action *action, 301 enum rte_port_in_action_type type) 302 { 303 void *data = action_data_get(action, type); 304 305 switch (type) { 306 case RTE_PORT_IN_ACTION_FLTR: 307 fltr_init(data, &action->cfg.fltr); 308 return; 309 310 case RTE_PORT_IN_ACTION_LB: 311 lb_init(data, &action->cfg.lb); 312 return; 313 314 default: 315 return; 316 } 317 } 318 319 struct rte_port_in_action * 320 rte_port_in_action_create(struct rte_port_in_action_profile *profile, 321 uint32_t socket_id) 322 { 323 struct rte_port_in_action *action; 324 size_t size; 325 uint32_t i; 326 327 /* Check input arguments */ 328 if ((profile == NULL) || 329 (profile->frozen == 0)) 330 return NULL; 331 332 /* Memory allocation */ 333 size = sizeof(struct rte_port_in_action) + profile->data.total_size; 334 size = RTE_CACHE_LINE_ROUNDUP(size); 335 336 action = rte_zmalloc_socket(NULL, 337 size, 338 RTE_CACHE_LINE_SIZE, 339 socket_id); 340 if (action == NULL) 341 return NULL; 342 343 /* Initialization */ 344 memcpy(&action->cfg, &profile->cfg, sizeof(profile->cfg)); 345 memcpy(&action->data, &profile->data, sizeof(profile->data)); 346 347 for (i = 0; i < RTE_PORT_IN_ACTION_MAX; i++) 348 if (action->cfg.action_mask & (1LLU << i)) 349 action_data_init(action, 350 (enum rte_port_in_action_type)i); 351 352 return action; 353 } 354 355 int 356 rte_port_in_action_apply(struct rte_port_in_action *action, 357 enum rte_port_in_action_type type, 358 void *action_params) 359 { 360 void *action_data; 361 362 /* Check input arguments */ 363 if ((action == NULL) || 364 (action_valid(type) == 0) || 365 ((action->cfg.action_mask & (1LLU << type)) == 0) || 366 (action_params == NULL)) 367 return -EINVAL; 368 369 /* Data update */ 370 action_data = action_data_get(action, type); 371 372 switch (type) { 373 case RTE_PORT_IN_ACTION_FLTR: 374 return fltr_apply(action_data, 375 action_params); 376 377 case RTE_PORT_IN_ACTION_LB: 378 return lb_apply(action_data, 379 action_params); 380 381 default: 382 return -EINVAL; 383 } 384 } 385 386 static int 387 ah_filter_on_match(struct rte_pipeline *p, 388 struct rte_mbuf **pkts, 389 uint32_t n_pkts, 390 void *arg) 391 { 392 struct rte_port_in_action *action = arg; 393 struct rte_port_in_action_fltr_config *cfg = &action->cfg.fltr; 394 uint64_t *key_mask = (uint64_t *) cfg->key_mask; 395 uint64_t *key = (uint64_t *) cfg->key; 396 uint32_t key_offset = cfg->key_offset; 397 struct fltr_data *data = action_data_get(action, 398 RTE_PORT_IN_ACTION_FLTR); 399 uint32_t i; 400 401 for (i = 0; i < n_pkts; i++) { 402 struct rte_mbuf *pkt = pkts[i]; 403 uint64_t *pkt_key = RTE_MBUF_METADATA_UINT64_PTR(pkt, 404 key_offset); 405 406 uint64_t xor0 = (pkt_key[0] & key_mask[0]) ^ key[0]; 407 uint64_t xor1 = (pkt_key[1] & key_mask[1]) ^ key[1]; 408 uint64_t or = xor0 | xor1; 409 410 if (or == 0) { 411 rte_pipeline_ah_packet_hijack(p, 1LLU << i); 412 rte_pipeline_port_out_packet_insert(p, 413 data->port_id, pkt); 414 } 415 } 416 417 return 0; 418 } 419 420 static int 421 ah_filter_on_mismatch(struct rte_pipeline *p, 422 struct rte_mbuf **pkts, 423 uint32_t n_pkts, 424 void *arg) 425 { 426 struct rte_port_in_action *action = arg; 427 struct rte_port_in_action_fltr_config *cfg = &action->cfg.fltr; 428 uint64_t *key_mask = (uint64_t *) cfg->key_mask; 429 uint64_t *key = (uint64_t *) cfg->key; 430 uint32_t key_offset = cfg->key_offset; 431 struct fltr_data *data = action_data_get(action, 432 RTE_PORT_IN_ACTION_FLTR); 433 uint32_t i; 434 435 for (i = 0; i < n_pkts; i++) { 436 struct rte_mbuf *pkt = pkts[i]; 437 uint64_t *pkt_key = RTE_MBUF_METADATA_UINT64_PTR(pkt, 438 key_offset); 439 440 uint64_t xor0 = (pkt_key[0] & key_mask[0]) ^ key[0]; 441 uint64_t xor1 = (pkt_key[1] & key_mask[1]) ^ key[1]; 442 uint64_t or = xor0 | xor1; 443 444 if (or) { 445 rte_pipeline_ah_packet_hijack(p, 1LLU << i); 446 rte_pipeline_port_out_packet_insert(p, 447 data->port_id, pkt); 448 } 449 } 450 451 return 0; 452 } 453 454 static int 455 ah_lb(struct rte_pipeline *p, 456 struct rte_mbuf **pkts, 457 uint32_t n_pkts, 458 void *arg) 459 { 460 struct rte_port_in_action *action = arg; 461 struct rte_port_in_action_lb_config *cfg = &action->cfg.lb; 462 struct lb_data *data = action_data_get(action, RTE_PORT_IN_ACTION_LB); 463 uint64_t pkt_mask = RTE_LEN2MASK(n_pkts, uint64_t); 464 uint32_t i; 465 466 rte_pipeline_ah_packet_hijack(p, pkt_mask); 467 468 for (i = 0; i < n_pkts; i++) { 469 struct rte_mbuf *pkt = pkts[i]; 470 uint8_t *pkt_key = RTE_MBUF_METADATA_UINT8_PTR(pkt, 471 cfg->key_offset); 472 473 uint64_t digest = cfg->f_hash(pkt_key, 474 cfg->key_mask, 475 cfg->key_size, 476 cfg->seed); 477 uint64_t pos = digest & (RTE_PORT_IN_ACTION_LB_TABLE_SIZE - 1); 478 uint32_t port_id = data->port_id[pos]; 479 480 rte_pipeline_port_out_packet_insert(p, port_id, pkt); 481 } 482 483 return 0; 484 } 485 486 static rte_pipeline_port_in_action_handler 487 ah_selector(struct rte_port_in_action *action) 488 { 489 if (action->cfg.action_mask == 0) 490 return NULL; 491 492 if (action->cfg.action_mask == 1LLU << RTE_PORT_IN_ACTION_FLTR) 493 return (action->cfg.fltr.filter_on_match) ? 494 ah_filter_on_match : ah_filter_on_mismatch; 495 496 if (action->cfg.action_mask == 1LLU << RTE_PORT_IN_ACTION_LB) 497 return ah_lb; 498 499 return NULL; 500 } 501 502 int 503 rte_port_in_action_params_get(struct rte_port_in_action *action, 504 struct rte_pipeline_port_in_params *params) 505 { 506 rte_pipeline_port_in_action_handler f_action; 507 508 /* Check input arguments */ 509 if ((action == NULL) || 510 (params == NULL)) 511 return -EINVAL; 512 513 f_action = ah_selector(action); 514 515 /* Fill in params */ 516 params->f_action = f_action; 517 params->arg_ah = (f_action) ? action : NULL; 518 519 return 0; 520 } 521 522 int 523 rte_port_in_action_free(struct rte_port_in_action *action) 524 { 525 if (action == NULL) 526 return 0; 527 528 rte_free(action); 529 530 return 0; 531 } 532