Data Fields | |
| uint32_t(* | rss_hash_fn )(struct snf_recv_req *r, void *context) |
| void * | rss_context |
| uint32_t(* snf_rss_mode_function::rss_hash_fn)(struct snf_recv_req *r, void *context) |
User-provided hash function. Users a provided with a valid snf_recv_req structure which contains a packet as received by Sniffer. It is up to the user to inspect and parse the packet to produce a unique 32-bit hash. The implementation will map the 32-bit into one of the rings allocated in snf_open.
In the example below, we replace the default hash function with a hash function that sends packets to different rings at every interval of 500 packets. This approach ignores the actual packet contents and the importance of flow affinity, we just want to spread the packet analysis to different rings and threads.
#define MAX_RINGS 8 #define PKT_INTERVAL 500 static uint32_t cnt[MAX_RINGS]; static uint32_t cur_ring = 0; static uint32_t custom_hash(struct snf_recv_req *r, void *context) { if (++cnt[cur_ring] == PKT_INTERVAL) { cnt[cur_ring] = 0; if (++cur_ring == MAX_RINGS) cur_ring = 0; } // Return cur_ring as the hash value, since Sniffer will apply a // modulo and the corresponding ring will receive the packet when // calling snf_recv() return cur_ring; } // At snf_open time, select a custom hash approach. struct snf_rss_params rssp; rssp.mode = SNF_RSS_FUNCTION; rssp.params.rss_function.rss_hash_fn = custom_hash; rssp.params.rss_function.rss_context = NULL; // Don't need a context // On board 0, we will open MAX_RINGS rings, use default flags, // select an 800 MB data ring and chose our custom hashing function. snf_handle_t hsnf; int rc = snf_open(0, MAX_RINGS, &rssp, 800, 0, &hsnf); if (rc) { perror("Error in snf_open"); exit(EXIT_FAILURE); }
User context that is reflected when the user-provided rss_hash_fn is called.
![]()
26 October 2010 Sniffer10G 1.0.2_pcap1.1.1