// 选择子HASH
static inline unsigned int __sel_hash(struct xfrm_selector *sel, unsigned short family, unsigned int hmask)
{
// 提前源和目的地址
xfrm_address_t *daddr = &sel->daddr;
xfrm_address_t *saddr = &sel->saddr;
unsigned int h = 0;
switch (family) {
// 用源,目的地址同时进行HASH
case AF_INET:
if (sel->prefixlen_d != 32 ||
sel->prefixlen_s != 32)
return hmask + 1;
h = __xfrm4_daddr_saddr_hash(daddr, saddr);
break;
case AF_INET6:
if (sel->prefixlen_d != 128 ||
sel->prefixlen_s != 128)
return hmask + 1;
h = __xfrm6_daddr_saddr_hash(daddr, saddr);
break;
};
// 高16位与低16位异或,高16位不变
h ^= (h >> 16);
// 与掩码相与, 其实HASH值中不带协议族因素, 因为地址本身就包含了
return h & hmask;
}
// 地址HASH
static inline unsigned int __addr_hash(xfrm_address_t *daddr, xfrm_address_t *saddr, unsigned short family, unsigned int hmask)
{
unsigned int h = 0;
switch (family) {
// 用源,目的地址同时进行HASH
case AF_INET:
h = __xfrm4_daddr_saddr_hash(daddr, saddr);
break;
case AF_INET6:
h = __xfrm6_daddr_saddr_hash(daddr, saddr);
break;
};
// 高16位与低16位异或,高16位不变
h ^= (h >> 16);
// 与掩码相与
return h & hmask;
}
/*
* Probe for the availability of crypto algorithms, and set the available
* flag for any algorithms found on the system. This is typically called by
* pfkey during userspace SA add, update or register.
*/
void xfrm_probe_algs(void)
{
// 内核必须定义CRYPTO选项, 否则就是空函数了
#ifdef CONFIG_CRYPTO
int i, status;
BUG_ON(in_softirq());
// 遍历认证算法数组
for (i = 0; i < aalg_entries(); i++) {
// 根据算法名称确定该HASH算法是否存在, 返回0不存在, 非0存在
status = crypto_has_hash(aalg_list[i].name, 0,
CRYPTO_ALG_ASYNC);
// 如果状态和原来的状态不同, 更改
if (aalg_list[i].available != status)
aalg_list[i].available = status;
}
// 遍历加密算法数组
for (i = 0; i < ealg_entries(); i++) {
// 根据算法名称确定该加密算法是否存在, 返回0不存在, 非0存在
status = crypto_has_blkcipher(ealg_list[i].name, 0,
CRYPTO_ALG_ASYNC);
// 如果状态和原来的状态不同, 更改
if (ealg_list[i].available != status)
ealg_list[i].available = status;
}
// 遍历压缩算法数组
for (i = 0; i < calg_entries(); i++) {
// 根据算法名称确定该压缩算法是否存在, 返回0不存在, 非0存在
status = crypto_has_comp(calg_list[i].name, 0,
CRYPTO_ALG_ASYNC);
// 如果状态和原来的状态不同, 更改
if (calg_list[i].available != status)
calg_list[i].available = status;
}
#endif
}
EXPORT_SYMBOL_GPL(xfrm_probe_algs);