global var and structure:
static DEFINE_PER_NET(struct hlist_head *, xfrm_state_byspi);
static struct xfrm_policy_afinfo *xfrm_policy_afinfo[NPROTO];
xfrm_policy_afinfo 定义一个大的数组,每一个元素对应一个地址族,如ipv4(AF_INET),ipv6(AF_INET6).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| struct xfrm_policy_afinfo { unsigned short family; rwlock_t lock; struct xfrm_type_map *type_map; struct dst_ops *dst_ops; void (*garbage_collect)(net_t net); int (*dst_lookup)(struct xfrm_dst **dst, struct flowi *fl); int (*get_saddr)(net_t net, xfrm_address_t *saddr, xfrm_address_t *daddr); struct dst_entry *(*find_bundle)(struct flowi *fl, struct xfrm_policy *policy); int (*bundle_create)(struct xfrm_policy *policy, struct xfrm_state **xfrm, int nx, struct flowi *fl, struct dst_entry **dst_p); void (*decode_session)(struct sk_buff *skb, struct flowi *fl); };
|
在struct xfrm_policy_afinfo中有一个元素
1 2 3 4 5
| struct xfrm_type_map *type_map; struct xfrm_type_map { rwlock_t lock; struct xfrm_type *map[256]; };
|
map 也是一个指针数组,其每个元素对应一个应用层的协议如 ESP(IPPROTO_ESP), AH, UDP(IPPROTO_UDP),TCP等。
两个相关的注册函数:
关于xfrm_policy_afinfo
1 2 3 4 5 6 7 8 9 10 11
| int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo);
static void __init xfrm4_policy_init(void) { xfrm_policy_register_afinfo(&xfrm4_policy_afinfo); }
static void __init xfrm6_policy_init(void) { xfrm_policy_register_afinfo(&xfrm6_policy_afinfo); }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo) { int err = 0; if (unlikely(afinfo == NULL)) return -EINVAL; if (unlikely(afinfo->family >= NPROTO)) return -EAFNOSUPPORT; write_lock(&xfrm_policy_afinfo_lock); if (unlikely(xfrm_policy_afinfo[afinfo->family] != NULL)) err = -ENOBUFS; else { struct dst_ops *dst_ops = afinfo->dst_ops; if (likely(dst_ops->kmem_cachep == NULL)) dst_ops->kmem_cachep = xfrm_dst_cache; if (likely(dst_ops->check == NULL)) dst_ops->check = xfrm_dst_check; if (likely(dst_ops->negative_advice == NULL)) dst_ops->negative_advice = xfrm_negative_advice; if (likely(dst_ops->link_failure == NULL)) dst_ops->link_failure = xfrm_link_failure; if (likely(afinfo->garbage_collect == NULL)) afinfo->garbage_collect = __xfrm_garbage_collect; xfrm_policy_afinfo[afinfo->family] = afinfo; } write_unlock(&xfrm_policy_afinfo_lock); return err; }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| int xfrm_register_type(struct xfrm_type *type, unsigned short family) { struct xfrm_policy_afinfo *afinfo = xfrm_policy_get_afinfo(family); struct xfrm_type_map *typemap; int err = 0;
if (unlikely(afinfo == NULL)) return -EAFNOSUPPORT; typemap = afinfo->type_map;
write_lock(&typemap->lock); if (likely(typemap->map[type->proto] == NULL)) typemap->map[type->proto] = type; else err = -EEXIST; write_unlock(&typemap->lock); xfrm_policy_put_afinfo(afinfo); return err; }
|