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) {
44 ilan
->locks
= kvmalloc(size
* sizeof(spinlock_t
), GFP_KERNEL
);
47 for (i
= 0; i
< size
; i
++)
48 spin_lock_init(&ilan
->locks
[i
]);
50 ilan
->locks_mask
= size
- 1;
55 static u32 hashrnd __read_mostly
;
56 static __always_inline
void __ila_hash_secret_init(void)
58 net_get_random_once(&hashrnd
, sizeof(hashrnd
));
61 static inline u32
ila_locator_hash(struct ila_locator loc
)
63 u32
*v
= (u32
*)loc
.v32
;
65 __ila_hash_secret_init();
66 return jhash_2words(v
[0], v
[1], hashrnd
);
69 static inline spinlock_t
*ila_get_lock(struct ila_net
*ilan
,
70 struct ila_locator loc
)
72 return &ilan
->locks
[ila_locator_hash(loc
) & ilan
->locks_mask
];
75 static inline int ila_cmp_wildcards(struct ila_map
*ila
,
76 struct ila_addr
*iaddr
, int ifindex
)
78 return (ila
->xp
.ifindex
&& ila
->xp
.ifindex
!= ifindex
);
81 static inline int ila_cmp_params(struct ila_map
*ila
,
82 struct ila_xlat_params
*xp
)
84 return (ila
->xp
.ifindex
!= xp
->ifindex
);
87 static int ila_cmpfn(struct rhashtable_compare_arg
*arg
,
90 const struct ila_map
*ila
= obj
;
92 return (ila
->xp
.ip
.locator_match
.v64
!= *(__be64
*)arg
->key
);
95 static inline int ila_order(struct ila_map
*ila
)
105 static const struct rhashtable_params rht_params
= {
107 .head_offset
= offsetof(struct ila_map
, node
),
108 .key_offset
= offsetof(struct ila_map
, xp
.ip
.locator_match
),
109 .key_len
= sizeof(u64
), /* identifier */
112 .automatic_shrinking
= true,
113 .obj_cmpfn
= ila_cmpfn
,
116 static struct genl_family ila_nl_family
;
118 static const struct nla_policy ila_nl_policy
[ILA_ATTR_MAX
+ 1] = {
119 [ILA_ATTR_LOCATOR
] = { .type
= NLA_U64
, },
120 [ILA_ATTR_LOCATOR_MATCH
] = { .type
= NLA_U64
, },
121 [ILA_ATTR_IFINDEX
] = { .type
= NLA_U32
, },
122 [ILA_ATTR_CSUM_MODE
] = { .type
= NLA_U8
, },
125 static int parse_nl_config(struct genl_info
*info
,
126 struct ila_xlat_params
*xp
)
128 memset(xp
, 0, sizeof(*xp
));
130 if (info
->attrs
[ILA_ATTR_LOCATOR
])
131 xp
->ip
.locator
.v64
= (__force __be64
)nla_get_u64(
132 info
->attrs
[ILA_ATTR_LOCATOR
]);
134 if (info
->attrs
[ILA_ATTR_LOCATOR_MATCH
])
135 xp
->ip
.locator_match
.v64
= (__force __be64
)nla_get_u64(
136 info
->attrs
[ILA_ATTR_LOCATOR_MATCH
]);
138 if (info
->attrs
[ILA_ATTR_CSUM_MODE
])
139 xp
->ip
.csum_mode
= nla_get_u8(info
->attrs
[ILA_ATTR_CSUM_MODE
]);
141 if (info
->attrs
[ILA_ATTR_IFINDEX
])
142 xp
->ifindex
= nla_get_s32(info
->attrs
[ILA_ATTR_IFINDEX
]);
147 /* Must be called with rcu readlock */
148 static inline struct ila_map
*ila_lookup_wildcards(struct ila_addr
*iaddr
,
150 struct ila_net
*ilan
)
154 ila
= rhashtable_lookup_fast(&ilan
->rhash_table
, &iaddr
->loc
,
157 if (!ila_cmp_wildcards(ila
, iaddr
, ifindex
))
159 ila
= rcu_access_pointer(ila
->next
);
165 /* Must be called with rcu readlock */
166 static inline struct ila_map
*ila_lookup_by_params(struct ila_xlat_params
*xp
,
167 struct ila_net
*ilan
)
171 ila
= rhashtable_lookup_fast(&ilan
->rhash_table
,
172 &xp
->ip
.locator_match
,
175 if (!ila_cmp_params(ila
, xp
))
177 ila
= rcu_access_pointer(ila
->next
);
183 static inline void ila_release(struct ila_map
*ila
)
188 static void ila_free_cb(void *ptr
, void *arg
)
190 struct ila_map
*ila
= (struct ila_map
*)ptr
, *next
;
192 /* Assume rcu_readlock held */
194 next
= rcu_access_pointer(ila
->next
);
200 static int ila_xlat_addr(struct sk_buff
*skb
, bool set_csum_neutral
);
203 ila_nf_input(void *priv
,
205 const struct nf_hook_state
*state
)
207 ila_xlat_addr(skb
, false);
211 static struct nf_hook_ops ila_nf_hook_ops
[] __read_mostly
= {
213 .hook
= ila_nf_input
,
215 .hooknum
= NF_INET_PRE_ROUTING
,
220 static int ila_add_mapping(struct net
*net
, struct ila_xlat_params
*xp
)
222 struct ila_net
*ilan
= net_generic(net
, ila_net_id
);
223 struct ila_map
*ila
, *head
;
224 spinlock_t
*lock
= ila_get_lock(ilan
, xp
->ip
.locator_match
);
227 if (!ilan
->hooks_registered
) {
228 /* We defer registering net hooks in the namespace until the
229 * first mapping is added.
231 err
= nf_register_net_hooks(net
, ila_nf_hook_ops
,
232 ARRAY_SIZE(ila_nf_hook_ops
));
236 ilan
->hooks_registered
= true;
239 ila
= kzalloc(sizeof(*ila
), GFP_KERNEL
);
243 ila_init_saved_csum(&xp
->ip
);
247 order
= ila_order(ila
);
251 head
= rhashtable_lookup_fast(&ilan
->rhash_table
,
252 &xp
->ip
.locator_match
,
255 /* New entry for the rhash_table */
256 err
= rhashtable_lookup_insert_fast(&ilan
->rhash_table
,
257 &ila
->node
, rht_params
);
259 struct ila_map
*tila
= head
, *prev
= NULL
;
262 if (!ila_cmp_params(tila
, xp
)) {
267 if (order
> ila_order(tila
))
271 tila
= rcu_dereference_protected(tila
->next
,
272 lockdep_is_held(lock
));
276 /* Insert in sub list of head */
277 RCU_INIT_POINTER(ila
->next
, tila
);
278 rcu_assign_pointer(prev
->next
, ila
);
280 /* Make this ila new head */
281 RCU_INIT_POINTER(ila
->next
, head
);
282 err
= rhashtable_replace_fast(&ilan
->rhash_table
,
284 &ila
->node
, rht_params
);
299 static int ila_del_mapping(struct net
*net
, struct ila_xlat_params
*xp
)
301 struct ila_net
*ilan
= net_generic(net
, ila_net_id
);
302 struct ila_map
*ila
, *head
, *prev
;
303 spinlock_t
*lock
= ila_get_lock(ilan
, xp
->ip
.locator_match
);
308 head
= rhashtable_lookup_fast(&ilan
->rhash_table
,
309 &xp
->ip
.locator_match
, rht_params
);
315 if (ila_cmp_params(ila
, xp
)) {
317 ila
= rcu_dereference_protected(ila
->next
,
318 lockdep_is_held(lock
));
325 /* Not head, just delete from list */
326 rcu_assign_pointer(prev
->next
, ila
->next
);
328 /* It is the head. If there is something in the
329 * sublist we need to make a new head.
331 head
= rcu_dereference_protected(ila
->next
,
332 lockdep_is_held(lock
));
334 /* Put first entry in the sublist into the
337 err
= rhashtable_replace_fast(
338 &ilan
->rhash_table
, &ila
->node
,
339 &head
->node
, rht_params
);
343 /* Entry no longer used */
344 err
= rhashtable_remove_fast(&ilan
->rhash_table
,
361 static int ila_nl_cmd_add_mapping(struct sk_buff
*skb
, struct genl_info
*info
)
363 struct net
*net
= genl_info_net(info
);
364 struct ila_xlat_params p
;
367 err
= parse_nl_config(info
, &p
);
371 return ila_add_mapping(net
, &p
);
374 static int ila_nl_cmd_del_mapping(struct sk_buff
*skb
, struct genl_info
*info
)
376 struct net
*net
= genl_info_net(info
);
377 struct ila_xlat_params xp
;
380 err
= parse_nl_config(info
, &xp
);
384 ila_del_mapping(net
, &xp
);
389 static int ila_fill_info(struct ila_map
*ila
, struct sk_buff
*msg
)
391 if (nla_put_u64_64bit(msg
, ILA_ATTR_LOCATOR
,
392 (__force u64
)ila
->xp
.ip
.locator
.v64
,
394 nla_put_u64_64bit(msg
, ILA_ATTR_LOCATOR_MATCH
,
395 (__force u64
)ila
->xp
.ip
.locator_match
.v64
,
397 nla_put_s32(msg
, ILA_ATTR_IFINDEX
, ila
->xp
.ifindex
) ||
398 nla_put_u32(msg
, ILA_ATTR_CSUM_MODE
, ila
->xp
.ip
.csum_mode
))
404 static int ila_dump_info(struct ila_map
*ila
,
405 u32 portid
, u32 seq
, u32 flags
,
406 struct sk_buff
*skb
, u8 cmd
)
410 hdr
= genlmsg_put(skb
, portid
, seq
, &ila_nl_family
, flags
, cmd
);
414 if (ila_fill_info(ila
, skb
) < 0)
415 goto nla_put_failure
;
417 genlmsg_end(skb
, hdr
);
421 genlmsg_cancel(skb
, hdr
);
425 static int ila_nl_cmd_get_mapping(struct sk_buff
*skb
, struct genl_info
*info
)
427 struct net
*net
= genl_info_net(info
);
428 struct ila_net
*ilan
= net_generic(net
, ila_net_id
);
430 struct ila_xlat_params xp
;
434 ret
= parse_nl_config(info
, &xp
);
438 msg
= nlmsg_new(NLMSG_DEFAULT_SIZE
, GFP_KERNEL
);
444 ila
= ila_lookup_by_params(&xp
, ilan
);
446 ret
= ila_dump_info(ila
,
448 info
->snd_seq
, 0, msg
,
457 return genlmsg_reply(msg
, info
);
464 struct ila_dump_iter
{
465 struct rhashtable_iter rhiter
;
468 static int ila_nl_dump_start(struct netlink_callback
*cb
)
470 struct net
*net
= sock_net(cb
->skb
->sk
);
471 struct ila_net
*ilan
= net_generic(net
, ila_net_id
);
472 struct ila_dump_iter
*iter
= (struct ila_dump_iter
*)cb
->args
[0];
475 iter
= kmalloc(sizeof(*iter
), GFP_KERNEL
);
479 cb
->args
[0] = (long)iter
;
482 return rhashtable_walk_init(&ilan
->rhash_table
, &iter
->rhiter
,
486 static int ila_nl_dump_done(struct netlink_callback
*cb
)
488 struct ila_dump_iter
*iter
= (struct ila_dump_iter
*)cb
->args
[0];
490 rhashtable_walk_exit(&iter
->rhiter
);
497 static int ila_nl_dump(struct sk_buff
*skb
, struct netlink_callback
*cb
)
499 struct ila_dump_iter
*iter
= (struct ila_dump_iter
*)cb
->args
[0];
500 struct rhashtable_iter
*rhiter
= &iter
->rhiter
;
504 ret
= rhashtable_walk_start(rhiter
);
505 if (ret
&& ret
!= -EAGAIN
)
509 ila
= rhashtable_walk_next(rhiter
);
512 if (PTR_ERR(ila
) == -EAGAIN
)
521 ret
= ila_dump_info(ila
, NETLINK_CB(cb
->skb
).portid
,
522 cb
->nlh
->nlmsg_seq
, NLM_F_MULTI
,
527 ila
= rcu_access_pointer(ila
->next
);
534 rhashtable_walk_stop(rhiter
);
538 static const struct genl_ops ila_nl_ops
[] = {
541 .doit
= ila_nl_cmd_add_mapping
,
542 .policy
= ila_nl_policy
,
543 .flags
= GENL_ADMIN_PERM
,
547 .doit
= ila_nl_cmd_del_mapping
,
548 .policy
= ila_nl_policy
,
549 .flags
= GENL_ADMIN_PERM
,
553 .doit
= ila_nl_cmd_get_mapping
,
554 .start
= ila_nl_dump_start
,
555 .dumpit
= ila_nl_dump
,
556 .done
= ila_nl_dump_done
,
557 .policy
= ila_nl_policy
,
561 static struct genl_family ila_nl_family __ro_after_init
= {
563 .name
= ILA_GENL_NAME
,
564 .version
= ILA_GENL_VERSION
,
565 .maxattr
= ILA_ATTR_MAX
,
567 .parallel_ops
= true,
568 .module
= THIS_MODULE
,
570 .n_ops
= ARRAY_SIZE(ila_nl_ops
),
573 #define ILA_HASH_TABLE_SIZE 1024
575 static __net_init
int ila_init_net(struct net
*net
)
578 struct ila_net
*ilan
= net_generic(net
, ila_net_id
);
580 err
= alloc_ila_locks(ilan
);
584 rhashtable_init(&ilan
->rhash_table
, &rht_params
);
589 static __net_exit
void ila_exit_net(struct net
*net
)
591 struct ila_net
*ilan
= net_generic(net
, ila_net_id
);
593 rhashtable_free_and_destroy(&ilan
->rhash_table
, ila_free_cb
, NULL
);
597 if (ilan
->hooks_registered
)
598 nf_unregister_net_hooks(net
, ila_nf_hook_ops
,
599 ARRAY_SIZE(ila_nf_hook_ops
));
602 static struct pernet_operations ila_net_ops
= {
603 .init
= ila_init_net
,
604 .exit
= ila_exit_net
,
606 .size
= sizeof(struct ila_net
),
609 static int ila_xlat_addr(struct sk_buff
*skb
, bool set_csum_neutral
)
612 struct ipv6hdr
*ip6h
= ipv6_hdr(skb
);
613 struct net
*net
= dev_net(skb
->dev
);
614 struct ila_net
*ilan
= net_generic(net
, ila_net_id
);
615 struct ila_addr
*iaddr
= ila_a2i(&ip6h
->daddr
);
617 /* Assumes skb contains a valid IPv6 header that is pulled */
619 if (!ila_addr_is_ila(iaddr
)) {
620 /* Type indicates this is not an ILA address */
626 ila
= ila_lookup_wildcards(iaddr
, skb
->dev
->ifindex
, ilan
);
628 ila_update_ipv6_locator(skb
, &ila
->xp
.ip
, set_csum_neutral
);
635 int __init
ila_xlat_init(void)
639 ret
= register_pernet_device(&ila_net_ops
);
643 ret
= genl_register_family(&ila_nl_family
);
650 unregister_pernet_device(&ila_net_ops
);
655 void ila_xlat_fini(void)
657 genl_unregister_family(&ila_nl_family
);
658 unregister_pernet_device(&ila_net_ops
);