I'm working on multicast and encountered this hash in linux code(ipmr.c). As far I understand, the hash table size is 64. And MFC_HASH takes highest 8 bits of ip destination address and highest 6 bits of source ip address. It XORs both and AND it with 63. Hence the result is bound to be between 0-63.
Please find the below code for more information.
struct mr_table {
struct list_head list;
possible_net_t net;
u32 id;
struct sock __rcu *mroute_sk;
struct timer_list ipmr_expire_timer;
struct list_head mfc_unres_queue;
struct list_head mfc_cache_array[MFC_LINES];
...
...
}
#define MFC_LINES 64
#ifdef __BIG_ENDIAN
#define MFC_HASH(a,b) ((((a)>>24)^((b)>>26))&(MFC_LINES-1))
#else
#define MFC_HASH(a,b) (((a)^((b)>>2))&(MFC_LINES-1))
#endif
What is special about this hash? How is it better than just adding the two ip addresses and doing a modulo by 63. Or just doing a modulo on the group ip address? Also if I want to increase the hash table size to 128 from 64 then is it enough if I change the MFC_LINE to 128? Or do I need to change the number of bits MFC_HASH uses from group-ip and source-ip? Can someone please help? My machine is big endian.
Thank you.
How is it better than just adding the two ip addresses and doing a modulo by 63.?
If you added two IP addresses and took modulo 64 (it should be 64, not 63) then higher bytes would be neglected as they are multiples of 0x40. The intent of this hash is to differentiate addresses based on highest address bits. That is why it first xors them and only then puts in [0, 63] range.
Example:
a: 255.0.0.0
b: 54.0.0.0
(a + b) = 35.0.0.2 (neglecting unsigned int overflow - hardware will discard leftmost bit)
35.0.0.0 % 64 = 0 ( 35.0.0.0 = 889192448 = 13893632 * 64 + 0)