Hello, On Sun, Mar 13, 2016 at 10:38 AM, ?? <zhangwqh at 126.com> wrote: > Hi all, > When I use the dpdk lookup function, I met the segment fault problem. Can > anybody help to look at why this happens. I will put the aim what I want to > do and the related piece of code, and my debug message, > > > This problem is that in dpdk multi process - client and server example, > dpdk-2.2.0/examples/multi_process/client_server_mp > My aim is that server create a hash table, then share it to client. Client > will write the hash table, server will read the hash table. I am using dpdk > hash table. What I did is that server create a hash table (table and array > entries), return the table address. I use memzone pass the table address to > client. In client, the second lookup gets segment fault. The system gets > crashed. I will put some related code here. > create hash table function: >
Let me see if I understand correctly. You're allocating a hash table on huge-page backed memory. You pass a pointer to that table over a shared memory structure. Is that correct? I don't think something being in a huge-page necessarily means it is shared. That is, allocating your hash table using rte_calloc in the primary isn't sufficient to make it available in the secondary. Further, even if it was, I do not think that it would work, because there are a bunch of pointers involved (i.e. ft->data). As far as I'm aware, each process has its own "view" of the shared memory. It maps it into its own local address space, and gives it an address according to what is currently available there. Most of my IPC with DPDK has involved passing packets around; I'm not sure what the strategy is for hash tables. Synchronization issues aside, I think you will need to put the hash table in its entirety in shared memory, and avoid global pointers: either offset into the shared memory, or have a structure with no pointers at all. From that, you can probably build up local pointers. Maybe somebody else can correct me or come up with a better idea. Hope that helps, Kyle > struct onvm_ft* > > onvm_ft_create(int cnt, int entry_size) { > > struct rte_hash* hash; > > struct onvm_ft* ft; > > struct rte_hash_parameters ipv4_hash_params = { > > .name = NULL, > > .entries = cnt, > > .key_len = sizeof(struct onvm_ft_ipv4_5tuple), > > .hash_func = NULL, > > .hash_func_init_val = 0, > > }; > > > > > char s[64]; > > /* create ipv4 hash table. use core number and cycle counter to get a > unique name. */ > > ipv4_hash_params.name = s; > > ipv4_hash_params.socket_id = rte_socket_id(); > > snprintf(s, sizeof(s), "onvm_ft_%d-%"PRIu64, rte_lcore_id(), > rte_get_tsc_cycles()); > > hash = rte_hash_create(&ipv4_hash_params); > > if (hash == NULL) { > > return NULL; > > } > > ft = (struct onvm_ft*)rte_calloc("table", 1, sizeof(struct onvm_ft), > 0); > > if (ft == NULL) { > > rte_hash_free(hash); > > return NULL; > > } > > ft->hash = hash; > > ft->cnt = cnt; > > ft->entry_size = entry_size; > > /* Create data array for storing values */ > > ft->data = rte_calloc("entry", cnt, entry_size, 0); > > if (ft->data == NULL) { > > rte_hash_free(hash); > > rte_free(ft); > > return NULL; > > } > > return ft; > > } > > > > > related structure: > > struct onvm_ft { > > struct rte_hash* hash; > > char* data; > > int cnt; > > int entry_size; > > }; > > > > > in server side, I will call the create function, use memzone share it to > client. The following is what I do: > > related variables: > > struct onvm_ft *sdn_ft; > > struct onvm_ft **sdn_ft_p; > > const struct rte_memzone *mz_ftp; > > > > > sdn_ft = onvm_ft_create(1024, sizeof(struct onvm_flow_entry)); > > if(sdn_ft == NULL) { > > rte_exit(EXIT_FAILURE, "Unable to create flow table\n"); > > } > > mz_ftp = rte_memzone_reserve(MZ_FTP_INFO, sizeof(struct onvm_ft *), > > rte_socket_id(), NO_FLAGS); > > if (mz_ftp == NULL) { > > rte_exit(EXIT_FAILURE, "Canot reserve memory zone for flow > table pointer\n"); > > } > > memset(mz_ftp->addr, 0, sizeof(struct onvm_ft *)); > > sdn_ft_p = mz_ftp->addr; > > *sdn_ft_p = sdn_ft; > > > > > In client side: > > struct onvm_ft *sdn_ft; > > static void > > map_flow_table(void) { > > const struct rte_memzone *mz_ftp; > > struct onvm_ft **ftp; > > > > > mz_ftp = rte_memzone_lookup(MZ_FTP_INFO); > > if (mz_ftp == NULL) > > rte_exit(EXIT_FAILURE, "Cannot get flow table pointer\n"); > > ftp = mz_ftp->addr; > > sdn_ft = *ftp; > > } > > > > > The following is my debug message: I set a breakpoint in lookup table line. > To narrow down the problem, I just send one flow. So the second time and the > first time, the packets are the same. > > For the first time, it works. I print out the parameters: inside the > onvm_ft_lookup function, if there is a related entry, it will return the > address by flow_entry. > > Breakpoint 1, datapath_handle_read (dp=0x7ffff00008c0) at > /home/zhangwei1984/openNetVM-master/openNetVM/examples/flow_table/sdn.c:191 > > 191 ret = onvm_ft_lookup(sdn_ft, fk, > (char**)&flow_entry); > > (gdb) print *sdn_ft > > $1 = {hash = 0x7fff32cce740, data = 0x7fff32cb0480 "", cnt = 1024, entry_size > = 56} > > (gdb) print *fk > > $2 = {src_addr = 419496202, dst_addr = 453050634, src_port = 53764, dst_port > = 11798, proto = 17 '\021'} > > (gdb) s > > onvm_ft_lookup (table=0x7fff32cbe4c0, key=0x7fff32b99d00, > data=0x7ffff68d2b00) at > /home/zhangwei1984/openNetVM-master/openNetVM/onvm/shared/onvm_flow_table.c:151 > > 151 softrss = onvm_softrss(key); > > (gdb) n > > 152 printf("software rss %d\n", softrss); > > (gdb) > > software rss 403183624 > > 154 tbl_index = rte_hash_lookup_with_hash(table->hash, (const void > *)key, softrss); > > (gdb) print table->hash > > $3 = (struct rte_hash *) 0x7fff32cce740 > > (gdb) print *key > > $4 = {src_addr = 419496202, dst_addr = 453050634, src_port = 53764, dst_port > = 11798, proto = 17 '\021'} > > (gdb) print softrss > > $5 = 403183624 > > (gdb) c > > > > > After I hit c, it will do the second lookup, > > Breakpoint 1, datapath_handle_read (dp=0x7ffff00008c0) at > /home/zhangwei1984/openNetVM-master/openNetVM/examples/flow_table/sdn.c:191 > > 191 ret = onvm_ft_lookup(sdn_ft, fk, > (char**)&flow_entry); > > (gdb) print *sdn_ft > > > $7 = {hash = 0x7fff32cce740, data = 0x7fff32cb0480 "", cnt = 1024, entry_size > = 56} > > (gdb) print *fk > > $8 = {src_addr = 419496202, dst_addr = 453050634, src_port = 53764, dst_port > = 11798, proto = 17 '\021'} > > (gdb) s > > onvm_ft_lookup (table=0x7fff32cbe4c0, key=0x7fff32b99c00, > data=0x7ffff68d2b00) at > /home/zhangwei1984/openNetVM-master/openNetVM/onvm/shared/onvm_flow_table.c:151 > > 151 softrss = onvm_softrss(key); > > (gdb) n > > 152 printf("software rss %d\n", softrss); > > (gdb) n > > software rss 403183624 > > 154 tbl_index = rte_hash_lookup_with_hash(table->hash, (const void > *)key, softrss); > > (gdb) print table->hash > > $9 = (struct rte_hash *) 0x7fff32cce740 > > (gdb) print *key > > $10 = {src_addr = 419496202, dst_addr = 453050634, src_port = 53764, dst_port > = 11798, proto = 17 '\021'} > > (gdb) print softrss > > $11 = 403183624 > > (gdb) n > > > > > > Program received signal SIGSEGV, Segmentation fault. > > 0x000000000045fb97 in __rte_hash_lookup_bulk () > > (gdb) bt > > #0 0x000000000045fb97 in __rte_hash_lookup_bulk () > > #1 0x0000000000000000 in ?? () > > > > > From the debug message, the parameters are exactly the same. I do not know > why it has the segmentation fault. > > my lookup function: > > int > > onvm_ft_lookup(struct onvm_ft* table, struct onvm_ft_ipv4_5tuple *key, char** > data) { > > int32_t tbl_index; > > uint32_t softrss; > > > > > softrss = onvm_softrss(key); > > printf("software rss %d\n", softrss); > > > > > tbl_index = rte_hash_lookup_with_hash(table->hash, (const void *)key, > softrss); > > if (tbl_index >= 0) { > > *data = onvm_ft_get_data(table, tbl_index); > > return 0; > > } > > else { > > return tbl_index; > > } > > }