1 #include <linux/jhash.h>
2 #include <linux/netfilter.h>
3 #include <linux/rcupdate.h>
4 #include <linux/rhashtable.h>
5 #include <linux/vmalloc.h>
6 #include <net/genetlink.h>
8 #include <net/netns/generic.h>
9 #include <uapi/linux/genetlink.h>
12 struct ila_xlat_params
{
18 struct ila_xlat_params xp
;
19 struct rhash_head node
;
20 struct ila_map __rcu
*next
;
24 static unsigned int ila_net_id
;
27 struct rhashtable rhash_table
;
28 spinlock_t
*locks
; /* Bucket locks for entry manipulation */
29 unsigned int locks_mask
;
30 bool hooks_registered
;
33 #define LOCKS_PER_CPU 10
35 static int alloc_ila_locks(struct ila_net
*ilan
)
38 unsigned int nr_pcpus
= num_possible_cpus();
40 nr_pcpus
= min_t(unsigned int, nr_pcpus
, 32UL);
41 size
= roundup_pow_of_two(nr_pcpus
* LOCKS_PER_CPU
);
43 if (sizeof(spinlock_t
) != 0) {
45 if (size
* sizeof(spinlock_t
) > PAGE_SIZE
)
46 ilan
->locks
= vmalloc(size
* sizeof(spinlock_t
));
49 ilan
->locks
= kmalloc_array(size
, sizeof(spinlock_t
),
53 for (i
= 0; i
< size
; i
++)
54 spin_lock_init(&ilan
->locks
[i
]);
56 ilan
->locks_mask
= size
- 1;
61 static u32 hashrnd __read_mostly
;
62 static __always_inline
void __ila_hash_secret_init(void)
64 net_get_random_once(&hashrnd
, sizeof(hashrnd
));
67 static inline u32
ila_locator_hash(struct ila_locator loc
)
69 u32
*v
= (u32
*)loc
.v32
;
71 return jhash_2words(v
[0], v
[1], hashrnd
);
74 static inline spinlock_t
*ila_get_lock(struct ila_net
*ilan
,
75 struct ila_locator loc
)
77 return &ilan
->locks
[ila_locator_hash(loc
) & ilan
->locks_mask
];
80 static inline int ila_cmp_wildcards(struct ila_map
*ila
,
81 struct ila_addr
*iaddr
, int ifindex
)
83 return (ila
->xp
.ifindex
&& ila
->xp
.ifindex
!= ifindex
);
86 static inline int ila_cmp_params(struct ila_map
*ila
,
87 struct ila_xlat_params
*xp
)
89 return (ila
->xp
.ifindex
!= xp
->ifindex
);
92 static int ila_cmpfn(struct rhashtable_compare_arg
*arg
,
95 const struct ila_map
*ila
= obj
;
97 return (ila
->xp
.ip
.locator_match
.v64
!= *(__be64
*)arg
->key
);
100 static inline int ila_order(struct ila_map
*ila
)
110 static const struct rhashtable_params rht_params
= {
112 .head_offset
= offsetof(struct ila_map
, node
),
113 .key_offset
= offsetof(struct ila_map
, xp
.ip
.locator_match
),
114 .key_len
= sizeof(u64
), /* identifier */
117 .automatic_shrinking
= true,
118 .obj_cmpfn
= ila_cmpfn
,
121 static struct genl_family ila_nl_family
;
123 static const struct nla_policy ila_nl_policy
[ILA_ATTR_MAX
+ 1] = {
124 [ILA_ATTR_LOCATOR
] = { .type
= NLA_U64
, },
125 [ILA_ATTR_LOCATOR_MATCH
] = { .type
= NLA_U64
, },
126 [ILA_ATTR_IFINDEX
] = { .type
= NLA_U32
, },
127 [ILA_ATTR_CSUM_MODE
] = { .type
= NLA_U8
, },
130 static int parse_nl_config(struct genl_info
*info
,
131 struct ila_xlat_params
*xp
)
133 memset(xp
, 0, sizeof(*xp
));
135 if (info
->attrs
[ILA_ATTR_LOCATOR
])
136 xp
->ip
.locator
.v64
= (__force __be64
)nla_get_u64(
137 info
->attrs
[ILA_ATTR_LOCATOR
]);
139 if (info
->attrs
[ILA_ATTR_LOCATOR_MATCH
])
140 xp
->ip
.locator_match
.v64
= (__force __be64
)nla_get_u64(
141 info
->attrs
[ILA_ATTR_LOCATOR_MATCH
]);
143 if (info
->attrs
[ILA_ATTR_CSUM_MODE
])
144 xp
->ip
.csum_mode
= nla_get_u8(info
->attrs
[ILA_ATTR_CSUM_MODE
]);
146 if (info
->attrs
[ILA_ATTR_IFINDEX
])
147 xp
->ifindex
= nla_get_s32(info
->attrs
[ILA_ATTR_IFINDEX
]);
152 /* Must be called with rcu readlock */
153 static inline struct ila_map
*ila_lookup_wildcards(struct ila_addr
*iaddr
,
155 struct ila_net
*ilan
)
159 ila
= rhashtable_lookup_fast(&ilan
->rhash_table
, &iaddr
->loc
,
162 if (!ila_cmp_wildcards(ila
, iaddr
, ifindex
))
164 ila
= rcu_access_pointer(ila
->next
);
170 /* Must be called with rcu readlock */
171 static inline struct ila_map
*ila_lookup_by_params(struct ila_xlat_params
*xp
,
172 struct ila_net
*ilan
)
176 ila
= rhashtable_lookup_fast(&ilan
->rhash_table
,
177 &xp
->ip
.locator_match
,
180 if (!ila_cmp_params(ila
, xp
))
182 ila
= rcu_access_pointer(ila
->next
);
188 static inline void ila_release(struct ila_map
*ila
)
193 static void ila_free_cb(void *ptr
, void *arg
)
195 struct ila_map
*ila
= (struct ila_map
*)ptr
, *next
;
197 /* Assume rcu_readlock held */
199 next
= rcu_access_pointer(ila
->next
);
205 static int ila_xlat_addr(struct sk_buff
*skb
, bool set_csum_neutral
);
208 ila_nf_input(void *priv
,
210 const struct nf_hook_state
*state
)
212 ila_xlat_addr(skb
, false);
216 static struct nf_hook_ops ila_nf_hook_ops
[] __read_mostly
= {
218 .hook
= ila_nf_input
,
220 .hooknum
= NF_INET_PRE_ROUTING
,
225 static int ila_add_mapping(struct net
*net
, struct ila_xlat_params
*xp
)
227 struct ila_net
*ilan
= net_generic(net
, ila_net_id
);
228 struct ila_map
*ila
, *head
;
229 spinlock_t
*lock
= ila_get_lock(ilan
, xp
->ip
.locator_match
);
232 if (!ilan
->hooks_registered
) {
233 /* We defer registering net hooks in the namespace until the
234 * first mapping is added.
236 err
= nf_register_net_hooks(net
, ila_nf_hook_ops
,
237 ARRAY_SIZE(ila_nf_hook_ops
));
241 ilan
->hooks_registered
= true;
244 ila
= kzalloc(sizeof(*ila
), GFP_KERNEL
);
248 ila_init_saved_csum(&xp
->ip
);
252 order
= ila_order(ila
);
256 head
= rhashtable_lookup_fast(&ilan
->rhash_table
,
257 &xp
->ip
.locator_match
,
260 /* New entry for the rhash_table */
261 err
= rhashtable_lookup_insert_fast(&ilan
->rhash_table
,
262 &ila
->node
, rht_params
);
264 struct ila_map
*tila
= head
, *prev
= NULL
;
267 if (!ila_cmp_params(tila
, xp
)) {
272 if (order
> ila_order(tila
))
276 tila
= rcu_dereference_protected(tila
->next
,
277 lockdep_is_held(lock
));
281 /* Insert in sub list of head */
282 RCU_INIT_POINTER(ila
->next
, tila
);
283 rcu_assign_pointer(prev
->next
, ila
);
285 /* Make this ila new head */
286 RCU_INIT_POINTER(ila
->next
, head
);
287 err
= rhashtable_replace_fast(&ilan
->rhash_table
,
289 &ila
->node
, rht_params
);
304 static int ila_del_mapping(struct net
*net
, struct ila_xlat_params
*xp
)
306 struct ila_net
*ilan
= net_generic(net
, ila_net_id
);
307 struct ila_map
*ila
, *head
, *prev
;
308 spinlock_t
*lock
= ila_get_lock(ilan
, xp
->ip
.locator_match
);
313 head
= rhashtable_lookup_fast(&ilan
->rhash_table
,
314 &xp
->ip
.locator_match
, rht_params
);
320 if (ila_cmp_params(ila
, xp
)) {
322 ila
= rcu_dereference_protected(ila
->next
,
323 lockdep_is_held(lock
));
330 /* Not head, just delete from list */
331 rcu_assign_pointer(prev
->next
, ila
->next
);
333 /* It is the head. If there is something in the
334 * sublist we need to make a new head.
336 head
= rcu_dereference_protected(ila
->next
,
337 lockdep_is_held(lock
));
339 /* Put first entry in the sublist into the
342 err
= rhashtable_replace_fast(
343 &ilan
->rhash_table
, &ila
->node
,
344 &head
->node
, rht_params
);
348 /* Entry no longer used */
349 err
= rhashtable_remove_fast(&ilan
->rhash_table
,
366 static int ila_nl_cmd_add_mapping(struct sk_buff
*skb
, struct genl_info
*info
)
368 struct net
*net
= genl_info_net(info
);
369 struct ila_xlat_params p
;
372 err
= parse_nl_config(info
, &p
);
376 return ila_add_mapping(net
, &p
);
379 static int ila_nl_cmd_del_mapping(struct sk_buff
*skb
, struct genl_info
*info
)
381 struct net
*net
= genl_info_net(info
);
382 struct ila_xlat_params xp
;
385 err
= parse_nl_config(info
, &xp
);
389 ila_del_mapping(net
, &xp
);
394 static int ila_fill_info(struct ila_map
*ila
, struct sk_buff
*msg
)
396 if (nla_put_u64_64bit(msg
, ILA_ATTR_LOCATOR
,
397 (__force u64
)ila
->xp
.ip
.locator
.v64
,
399 nla_put_u64_64bit(msg
, ILA_ATTR_LOCATOR_MATCH
,
400 (__force u64
)ila
->xp
.ip
.locator_match
.v64
,
402 nla_put_s32(msg
, ILA_ATTR_IFINDEX
, ila
->xp
.ifindex
) ||
403 nla_put_u32(msg
, ILA_ATTR_CSUM_MODE
, ila
->xp
.ip
.csum_mode
))
409 static int ila_dump_info(struct ila_map
*ila
,
410 u32 portid
, u32 seq
, u32 flags
,
411 struct sk_buff
*skb
, u8 cmd
)
415 hdr
= genlmsg_put(skb
, portid
, seq
, &ila_nl_family
, flags
, cmd
);
419 if (ila_fill_info(ila
, skb
) < 0)
420 goto nla_put_failure
;
422 genlmsg_end(skb
, hdr
);
426 genlmsg_cancel(skb
, hdr
);
430 static int ila_nl_cmd_get_mapping(struct sk_buff
*skb
, struct genl_info
*info
)
432 struct net
*net
= genl_info_net(info
);
433 struct ila_net
*ilan
= net_generic(net
, ila_net_id
);
435 struct ila_xlat_params xp
;
439 ret
= parse_nl_config(info
, &xp
);
443 msg
= nlmsg_new(NLMSG_DEFAULT_SIZE
, GFP_KERNEL
);
449 ila
= ila_lookup_by_params(&xp
, ilan
);
451 ret
= ila_dump_info(ila
,
453 info
->snd_seq
, 0, msg
,
462 return genlmsg_reply(msg
, info
);
469 struct ila_dump_iter
{
470 struct rhashtable_iter rhiter
;
473 static int ila_nl_dump_start(struct netlink_callback
*cb
)
475 struct net
*net
= sock_net(cb
->skb
->sk
);
476 struct ila_net
*ilan
= net_generic(net
, ila_net_id
);
477 struct ila_dump_iter
*iter
= (struct ila_dump_iter
*)cb
->args
[0];
480 iter
= kmalloc(sizeof(*iter
), GFP_KERNEL
);
484 cb
->args
[0] = (long)iter
;
487 return rhashtable_walk_init(&ilan
->rhash_table
, &iter
->rhiter
,
491 static int ila_nl_dump_done(struct netlink_callback
*cb
)
493 struct ila_dump_iter
*iter
= (struct ila_dump_iter
*)cb
->args
[0];
495 rhashtable_walk_exit(&iter
->rhiter
);
502 static int ila_nl_dump(struct sk_buff
*skb
, struct netlink_callback
*cb
)
504 struct ila_dump_iter
*iter
= (struct ila_dump_iter
*)cb
->args
[0];
505 struct rhashtable_iter
*rhiter
= &iter
->rhiter
;
509 ret
= rhashtable_walk_start(rhiter
);
510 if (ret
&& ret
!= -EAGAIN
)
514 ila
= rhashtable_walk_next(rhiter
);
517 if (PTR_ERR(ila
) == -EAGAIN
)
526 ret
= ila_dump_info(ila
, NETLINK_CB(cb
->skb
).portid
,
527 cb
->nlh
->nlmsg_seq
, NLM_F_MULTI
,
532 ila
= rcu_access_pointer(ila
->next
);
539 rhashtable_walk_stop(rhiter
);
543 static const struct genl_ops ila_nl_ops
[] = {
546 .doit
= ila_nl_cmd_add_mapping
,
547 .policy
= ila_nl_policy
,
548 .flags
= GENL_ADMIN_PERM
,
552 .doit
= ila_nl_cmd_del_mapping
,
553 .policy
= ila_nl_policy
,
554 .flags
= GENL_ADMIN_PERM
,
558 .doit
= ila_nl_cmd_get_mapping
,
559 .start
= ila_nl_dump_start
,
560 .dumpit
= ila_nl_dump
,
561 .done
= ila_nl_dump_done
,
562 .policy
= ila_nl_policy
,
566 static struct genl_family ila_nl_family __ro_after_init
= {
568 .name
= ILA_GENL_NAME
,
569 .version
= ILA_GENL_VERSION
,
570 .maxattr
= ILA_ATTR_MAX
,
572 .parallel_ops
= true,
573 .module
= THIS_MODULE
,
575 .n_ops
= ARRAY_SIZE(ila_nl_ops
),
578 #define ILA_HASH_TABLE_SIZE 1024
580 static __net_init
int ila_init_net(struct net
*net
)
583 struct ila_net
*ilan
= net_generic(net
, ila_net_id
);
585 err
= alloc_ila_locks(ilan
);
589 rhashtable_init(&ilan
->rhash_table
, &rht_params
);
594 static __net_exit
void ila_exit_net(struct net
*net
)
596 struct ila_net
*ilan
= net_generic(net
, ila_net_id
);
598 rhashtable_free_and_destroy(&ilan
->rhash_table
, ila_free_cb
, NULL
);
602 if (ilan
->hooks_registered
)
603 nf_unregister_net_hooks(net
, ila_nf_hook_ops
,
604 ARRAY_SIZE(ila_nf_hook_ops
));
607 static struct pernet_operations ila_net_ops
= {
608 .init
= ila_init_net
,
609 .exit
= ila_exit_net
,
611 .size
= sizeof(struct ila_net
),
614 static int ila_xlat_addr(struct sk_buff
*skb
, bool set_csum_neutral
)
617 struct ipv6hdr
*ip6h
= ipv6_hdr(skb
);
618 struct net
*net
= dev_net(skb
->dev
);
619 struct ila_net
*ilan
= net_generic(net
, ila_net_id
);
620 struct ila_addr
*iaddr
= ila_a2i(&ip6h
->daddr
);
622 /* Assumes skb contains a valid IPv6 header that is pulled */
624 if (!ila_addr_is_ila(iaddr
)) {
625 /* Type indicates this is not an ILA address */
631 ila
= ila_lookup_wildcards(iaddr
, skb
->dev
->ifindex
, ilan
);
633 ila_update_ipv6_locator(skb
, &ila
->xp
.ip
, set_csum_neutral
);
640 int __init
ila_xlat_init(void)
644 ret
= register_pernet_device(&ila_net_ops
);
648 ret
= genl_register_family(&ila_nl_family
);
655 unregister_pernet_device(&ila_net_ops
);
660 void ila_xlat_fini(void)
662 genl_unregister_family(&ila_nl_family
);
663 unregister_pernet_device(&ila_net_ops
);