1474572d2SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause 2474572d2SBruce Richardson * Copyright(c) 2010-2016 Intel Corporation 3474572d2SBruce Richardson */ 4474572d2SBruce Richardson 5474572d2SBruce Richardson #include <stdio.h> 6474572d2SBruce Richardson #include <stdlib.h> 7474572d2SBruce Richardson #include <stdint.h> 8474572d2SBruce Richardson 9474572d2SBruce Richardson #include <rte_log.h> 10474572d2SBruce Richardson #include <rte_ethdev.h> 11474572d2SBruce Richardson #include <rte_ether.h> 12474572d2SBruce Richardson #include <rte_ip.h> 13474572d2SBruce Richardson #include <rte_byteorder.h> 14474572d2SBruce Richardson 15474572d2SBruce Richardson #include <rte_port_ring.h> 16474572d2SBruce Richardson #include <rte_table_acl.h> 17474572d2SBruce Richardson #include <rte_pipeline.h> 18474572d2SBruce Richardson 19474572d2SBruce Richardson #include "main.h" 20474572d2SBruce Richardson 21474572d2SBruce Richardson enum { 22474572d2SBruce Richardson PROTO_FIELD_IPV4, 23474572d2SBruce Richardson SRC_FIELD_IPV4, 24474572d2SBruce Richardson DST_FIELD_IPV4, 25474572d2SBruce Richardson SRCP_FIELD_IPV4, 26474572d2SBruce Richardson DSTP_FIELD_IPV4, 27474572d2SBruce Richardson NUM_FIELDS_IPV4 28474572d2SBruce Richardson }; 29474572d2SBruce Richardson 30474572d2SBruce Richardson /* 31474572d2SBruce Richardson * Here we define the 'shape' of the data we're searching for, 32474572d2SBruce Richardson * by defining the meta-data of the ACL rules. 33474572d2SBruce Richardson * in this case, we're defining 5 tuples. IP addresses, ports, 34474572d2SBruce Richardson * and protocol. 35474572d2SBruce Richardson */ 36474572d2SBruce Richardson struct rte_acl_field_def ipv4_field_formats[NUM_FIELDS_IPV4] = { 37474572d2SBruce Richardson { 38474572d2SBruce Richardson .type = RTE_ACL_FIELD_TYPE_BITMASK, 39474572d2SBruce Richardson .size = sizeof(uint8_t), 40474572d2SBruce Richardson .field_index = PROTO_FIELD_IPV4, 41474572d2SBruce Richardson .input_index = PROTO_FIELD_IPV4, 426d13ea8eSOlivier Matz .offset = sizeof(struct rte_ether_hdr) + 43*a7c528e5SOlivier Matz offsetof(struct rte_ipv4_hdr, next_proto_id), 44474572d2SBruce Richardson }, 45474572d2SBruce Richardson { 46474572d2SBruce Richardson .type = RTE_ACL_FIELD_TYPE_MASK, 47474572d2SBruce Richardson .size = sizeof(uint32_t), 48474572d2SBruce Richardson .field_index = SRC_FIELD_IPV4, 49474572d2SBruce Richardson .input_index = SRC_FIELD_IPV4, 506d13ea8eSOlivier Matz .offset = sizeof(struct rte_ether_hdr) + 51*a7c528e5SOlivier Matz offsetof(struct rte_ipv4_hdr, src_addr), 52474572d2SBruce Richardson }, 53474572d2SBruce Richardson { 54474572d2SBruce Richardson .type = RTE_ACL_FIELD_TYPE_MASK, 55474572d2SBruce Richardson .size = sizeof(uint32_t), 56474572d2SBruce Richardson .field_index = DST_FIELD_IPV4, 57474572d2SBruce Richardson .input_index = DST_FIELD_IPV4, 586d13ea8eSOlivier Matz .offset = sizeof(struct rte_ether_hdr) + 59*a7c528e5SOlivier Matz offsetof(struct rte_ipv4_hdr, dst_addr), 60474572d2SBruce Richardson }, 61474572d2SBruce Richardson { 62474572d2SBruce Richardson .type = RTE_ACL_FIELD_TYPE_RANGE, 63474572d2SBruce Richardson .size = sizeof(uint16_t), 64474572d2SBruce Richardson .field_index = SRCP_FIELD_IPV4, 65474572d2SBruce Richardson .input_index = SRCP_FIELD_IPV4, 666d13ea8eSOlivier Matz .offset = sizeof(struct rte_ether_hdr) + 67*a7c528e5SOlivier Matz sizeof(struct rte_ipv4_hdr), 68474572d2SBruce Richardson }, 69474572d2SBruce Richardson { 70474572d2SBruce Richardson .type = RTE_ACL_FIELD_TYPE_RANGE, 71474572d2SBruce Richardson .size = sizeof(uint16_t), 72474572d2SBruce Richardson .field_index = DSTP_FIELD_IPV4, 73474572d2SBruce Richardson .input_index = SRCP_FIELD_IPV4, 746d13ea8eSOlivier Matz .offset = sizeof(struct rte_ether_hdr) + 75*a7c528e5SOlivier Matz sizeof(struct rte_ipv4_hdr) + sizeof(uint16_t), 76474572d2SBruce Richardson }, 77474572d2SBruce Richardson }; 78474572d2SBruce Richardson 79474572d2SBruce Richardson 80474572d2SBruce Richardson 81474572d2SBruce Richardson void 82474572d2SBruce Richardson app_main_loop_worker_pipeline_acl(void) { 83474572d2SBruce Richardson struct rte_pipeline_params pipeline_params = { 84474572d2SBruce Richardson .name = "pipeline", 85474572d2SBruce Richardson .socket_id = rte_socket_id(), 86474572d2SBruce Richardson }; 87474572d2SBruce Richardson 88474572d2SBruce Richardson struct rte_pipeline *p; 89474572d2SBruce Richardson uint32_t port_in_id[APP_MAX_PORTS]; 90474572d2SBruce Richardson uint32_t port_out_id[APP_MAX_PORTS]; 91474572d2SBruce Richardson uint32_t table_id; 92474572d2SBruce Richardson uint32_t i; 93474572d2SBruce Richardson 94474572d2SBruce Richardson RTE_LOG(INFO, USER1, 95474572d2SBruce Richardson "Core %u is doing work (pipeline with ACL table)\n", 96474572d2SBruce Richardson rte_lcore_id()); 97474572d2SBruce Richardson 98474572d2SBruce Richardson /* Pipeline configuration */ 99474572d2SBruce Richardson p = rte_pipeline_create(&pipeline_params); 100474572d2SBruce Richardson if (p == NULL) 101474572d2SBruce Richardson rte_panic("Unable to configure the pipeline\n"); 102474572d2SBruce Richardson 103474572d2SBruce Richardson /* Input port configuration */ 104474572d2SBruce Richardson for (i = 0; i < app.n_ports; i++) { 105474572d2SBruce Richardson struct rte_port_ring_reader_params port_ring_params = { 106474572d2SBruce Richardson .ring = app.rings_rx[i], 107474572d2SBruce Richardson }; 108474572d2SBruce Richardson 109474572d2SBruce Richardson struct rte_pipeline_port_in_params port_params = { 110474572d2SBruce Richardson .ops = &rte_port_ring_reader_ops, 111474572d2SBruce Richardson .arg_create = (void *) &port_ring_params, 112474572d2SBruce Richardson .f_action = NULL, 113474572d2SBruce Richardson .arg_ah = NULL, 114474572d2SBruce Richardson .burst_size = app.burst_size_worker_read, 115474572d2SBruce Richardson }; 116474572d2SBruce Richardson 117474572d2SBruce Richardson if (rte_pipeline_port_in_create(p, &port_params, 118474572d2SBruce Richardson &port_in_id[i])) 119474572d2SBruce Richardson rte_panic("Unable to configure input port for " 120474572d2SBruce Richardson "ring %d\n", i); 121474572d2SBruce Richardson } 122474572d2SBruce Richardson 123474572d2SBruce Richardson /* Output port configuration */ 124474572d2SBruce Richardson for (i = 0; i < app.n_ports; i++) { 125474572d2SBruce Richardson struct rte_port_ring_writer_params port_ring_params = { 126474572d2SBruce Richardson .ring = app.rings_tx[i], 127474572d2SBruce Richardson .tx_burst_sz = app.burst_size_worker_write, 128474572d2SBruce Richardson }; 129474572d2SBruce Richardson 130474572d2SBruce Richardson struct rte_pipeline_port_out_params port_params = { 131474572d2SBruce Richardson .ops = &rte_port_ring_writer_ops, 132474572d2SBruce Richardson .arg_create = (void *) &port_ring_params, 133474572d2SBruce Richardson .f_action = NULL, 134474572d2SBruce Richardson .arg_ah = NULL, 135474572d2SBruce Richardson }; 136474572d2SBruce Richardson 137474572d2SBruce Richardson if (rte_pipeline_port_out_create(p, &port_params, 138474572d2SBruce Richardson &port_out_id[i])) 139474572d2SBruce Richardson rte_panic("Unable to configure output port for " 140474572d2SBruce Richardson "ring %d\n", i); 141474572d2SBruce Richardson } 142474572d2SBruce Richardson 143474572d2SBruce Richardson /* Table configuration */ 144474572d2SBruce Richardson { 145474572d2SBruce Richardson struct rte_table_acl_params table_acl_params = { 146474572d2SBruce Richardson .name = "test", /* unique identifier for acl contexts */ 147474572d2SBruce Richardson .n_rules = 1 << 5, 148474572d2SBruce Richardson .n_rule_fields = DIM(ipv4_field_formats), 149474572d2SBruce Richardson }; 150474572d2SBruce Richardson 151474572d2SBruce Richardson /* Copy in the rule meta-data defined above into the params */ 152474572d2SBruce Richardson memcpy(table_acl_params.field_format, ipv4_field_formats, 153474572d2SBruce Richardson sizeof(ipv4_field_formats)); 154474572d2SBruce Richardson 155474572d2SBruce Richardson struct rte_pipeline_table_params table_params = { 156474572d2SBruce Richardson .ops = &rte_table_acl_ops, 157474572d2SBruce Richardson .arg_create = &table_acl_params, 158474572d2SBruce Richardson .f_action_hit = NULL, 159474572d2SBruce Richardson .f_action_miss = NULL, 160474572d2SBruce Richardson .arg_ah = NULL, 161474572d2SBruce Richardson .action_data_size = 0, 162474572d2SBruce Richardson }; 163474572d2SBruce Richardson 164474572d2SBruce Richardson if (rte_pipeline_table_create(p, &table_params, &table_id)) 165474572d2SBruce Richardson rte_panic("Unable to configure the ACL table\n"); 166474572d2SBruce Richardson } 167474572d2SBruce Richardson 168474572d2SBruce Richardson /* Interconnecting ports and tables */ 169474572d2SBruce Richardson for (i = 0; i < app.n_ports; i++) 170474572d2SBruce Richardson if (rte_pipeline_port_in_connect_to_table(p, port_in_id[i], 171474572d2SBruce Richardson table_id)) 172474572d2SBruce Richardson rte_panic("Unable to connect input port %u to " 173474572d2SBruce Richardson "table %u\n", port_in_id[i], table_id); 174474572d2SBruce Richardson 175474572d2SBruce Richardson /* Add entries to tables */ 176474572d2SBruce Richardson for (i = 0; i < app.n_ports; i++) { 177474572d2SBruce Richardson struct rte_pipeline_table_entry table_entry = { 178474572d2SBruce Richardson .action = RTE_PIPELINE_ACTION_PORT, 179474572d2SBruce Richardson {.port_id = port_out_id[i & (app.n_ports - 1)]}, 180474572d2SBruce Richardson }; 181474572d2SBruce Richardson struct rte_table_acl_rule_add_params rule_params; 182474572d2SBruce Richardson struct rte_pipeline_table_entry *entry_ptr; 183474572d2SBruce Richardson int key_found, ret; 184474572d2SBruce Richardson 185474572d2SBruce Richardson memset(&rule_params, 0, sizeof(rule_params)); 186474572d2SBruce Richardson 187474572d2SBruce Richardson /* Set the rule values */ 188474572d2SBruce Richardson rule_params.field_value[SRC_FIELD_IPV4].value.u32 = 0; 189474572d2SBruce Richardson rule_params.field_value[SRC_FIELD_IPV4].mask_range.u32 = 0; 190474572d2SBruce Richardson rule_params.field_value[DST_FIELD_IPV4].value.u32 = 191474572d2SBruce Richardson i << (24 - __builtin_popcount(app.n_ports - 1)); 192474572d2SBruce Richardson rule_params.field_value[DST_FIELD_IPV4].mask_range.u32 = 193474572d2SBruce Richardson 8 + __builtin_popcount(app.n_ports - 1); 194474572d2SBruce Richardson rule_params.field_value[SRCP_FIELD_IPV4].value.u16 = 0; 195474572d2SBruce Richardson rule_params.field_value[SRCP_FIELD_IPV4].mask_range.u16 = 196474572d2SBruce Richardson UINT16_MAX; 197474572d2SBruce Richardson rule_params.field_value[DSTP_FIELD_IPV4].value.u16 = 0; 198474572d2SBruce Richardson rule_params.field_value[DSTP_FIELD_IPV4].mask_range.u16 = 199474572d2SBruce Richardson UINT16_MAX; 200474572d2SBruce Richardson rule_params.field_value[PROTO_FIELD_IPV4].value.u8 = 0; 201474572d2SBruce Richardson rule_params.field_value[PROTO_FIELD_IPV4].mask_range.u8 = 0; 202474572d2SBruce Richardson 203474572d2SBruce Richardson rule_params.priority = 0; 204474572d2SBruce Richardson 205474572d2SBruce Richardson uint32_t dst_addr = rule_params.field_value[DST_FIELD_IPV4]. 206474572d2SBruce Richardson value.u32; 207474572d2SBruce Richardson uint32_t dst_mask = 208474572d2SBruce Richardson rule_params.field_value[DST_FIELD_IPV4].mask_range.u32; 209474572d2SBruce Richardson 210474572d2SBruce Richardson printf("Adding rule to ACL table (IPv4 destination = " 211474572d2SBruce Richardson "%u.%u.%u.%u/%u => port out = %u)\n", 212474572d2SBruce Richardson (dst_addr & 0xFF000000) >> 24, 213474572d2SBruce Richardson (dst_addr & 0x00FF0000) >> 16, 214474572d2SBruce Richardson (dst_addr & 0x0000FF00) >> 8, 215474572d2SBruce Richardson dst_addr & 0x000000FF, 216474572d2SBruce Richardson dst_mask, 217474572d2SBruce Richardson table_entry.port_id); 218474572d2SBruce Richardson 219474572d2SBruce Richardson /* For ACL, add needs an rte_table_acl_rule_add_params struct */ 220474572d2SBruce Richardson ret = rte_pipeline_table_entry_add(p, table_id, &rule_params, 221474572d2SBruce Richardson &table_entry, &key_found, &entry_ptr); 222474572d2SBruce Richardson if (ret < 0) 223474572d2SBruce Richardson rte_panic("Unable to add entry to table %u (%d)\n", 224474572d2SBruce Richardson table_id, ret); 225474572d2SBruce Richardson } 226474572d2SBruce Richardson 227474572d2SBruce Richardson /* Enable input ports */ 228474572d2SBruce Richardson for (i = 0; i < app.n_ports; i++) 229474572d2SBruce Richardson if (rte_pipeline_port_in_enable(p, port_in_id[i])) 230474572d2SBruce Richardson rte_panic("Unable to enable input port %u\n", 231474572d2SBruce Richardson port_in_id[i]); 232474572d2SBruce Richardson 233474572d2SBruce Richardson /* Check pipeline consistency */ 234474572d2SBruce Richardson if (rte_pipeline_check(p) < 0) 235474572d2SBruce Richardson rte_panic("Pipeline consistency check failed\n"); 236474572d2SBruce Richardson 237474572d2SBruce Richardson /* Run-time */ 238474572d2SBruce Richardson #if APP_FLUSH == 0 239474572d2SBruce Richardson for ( ; ; ) 240474572d2SBruce Richardson rte_pipeline_run(p); 241474572d2SBruce Richardson #else 242474572d2SBruce Richardson for (i = 0; ; i++) { 243474572d2SBruce Richardson rte_pipeline_run(p); 244474572d2SBruce Richardson 245474572d2SBruce Richardson if ((i & APP_FLUSH) == 0) 246474572d2SBruce Richardson rte_pipeline_flush(p); 247474572d2SBruce Richardson } 248474572d2SBruce Richardson #endif 249474572d2SBruce Richardson } 250