xref: /openbmc/linux/net/ipv6/ila/ila_xlat.c (revision e6dec923)
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>
7 #include <net/ila.h>
8 #include <net/netns/generic.h>
9 #include <uapi/linux/genetlink.h>
10 #include "ila.h"
11 
12 struct ila_xlat_params {
13 	struct ila_params ip;
14 	int ifindex;
15 };
16 
17 struct ila_map {
18 	struct ila_xlat_params xp;
19 	struct rhash_head node;
20 	struct ila_map __rcu *next;
21 	struct rcu_head rcu;
22 };
23 
24 static unsigned int ila_net_id;
25 
26 struct ila_net {
27 	struct rhashtable rhash_table;
28 	spinlock_t *locks; /* Bucket locks for entry manipulation */
29 	unsigned int locks_mask;
30 	bool hooks_registered;
31 };
32 
33 #define	LOCKS_PER_CPU 10
34 
35 static int alloc_ila_locks(struct ila_net *ilan)
36 {
37 	unsigned int i, size;
38 	unsigned int nr_pcpus = num_possible_cpus();
39 
40 	nr_pcpus = min_t(unsigned int, nr_pcpus, 32UL);
41 	size = roundup_pow_of_two(nr_pcpus * LOCKS_PER_CPU);
42 
43 	if (sizeof(spinlock_t) != 0) {
44 		ilan->locks = kvmalloc(size * sizeof(spinlock_t), GFP_KERNEL);
45 		if (!ilan->locks)
46 			return -ENOMEM;
47 		for (i = 0; i < size; i++)
48 			spin_lock_init(&ilan->locks[i]);
49 	}
50 	ilan->locks_mask = size - 1;
51 
52 	return 0;
53 }
54 
55 static u32 hashrnd __read_mostly;
56 static __always_inline void __ila_hash_secret_init(void)
57 {
58 	net_get_random_once(&hashrnd, sizeof(hashrnd));
59 }
60 
61 static inline u32 ila_locator_hash(struct ila_locator loc)
62 {
63 	u32 *v = (u32 *)loc.v32;
64 
65 	__ila_hash_secret_init();
66 	return jhash_2words(v[0], v[1], hashrnd);
67 }
68 
69 static inline spinlock_t *ila_get_lock(struct ila_net *ilan,
70 				       struct ila_locator loc)
71 {
72 	return &ilan->locks[ila_locator_hash(loc) & ilan->locks_mask];
73 }
74 
75 static inline int ila_cmp_wildcards(struct ila_map *ila,
76 				    struct ila_addr *iaddr, int ifindex)
77 {
78 	return (ila->xp.ifindex && ila->xp.ifindex != ifindex);
79 }
80 
81 static inline int ila_cmp_params(struct ila_map *ila,
82 				 struct ila_xlat_params *xp)
83 {
84 	return (ila->xp.ifindex != xp->ifindex);
85 }
86 
87 static int ila_cmpfn(struct rhashtable_compare_arg *arg,
88 		     const void *obj)
89 {
90 	const struct ila_map *ila = obj;
91 
92 	return (ila->xp.ip.locator_match.v64 != *(__be64 *)arg->key);
93 }
94 
95 static inline int ila_order(struct ila_map *ila)
96 {
97 	int score = 0;
98 
99 	if (ila->xp.ifindex)
100 		score += 1 << 1;
101 
102 	return score;
103 }
104 
105 static const struct rhashtable_params rht_params = {
106 	.nelem_hint = 1024,
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 */
110 	.max_size = 1048576,
111 	.min_size = 256,
112 	.automatic_shrinking = true,
113 	.obj_cmpfn = ila_cmpfn,
114 };
115 
116 static struct genl_family ila_nl_family;
117 
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, },
123 };
124 
125 static int parse_nl_config(struct genl_info *info,
126 			   struct ila_xlat_params *xp)
127 {
128 	memset(xp, 0, sizeof(*xp));
129 
130 	if (info->attrs[ILA_ATTR_LOCATOR])
131 		xp->ip.locator.v64 = (__force __be64)nla_get_u64(
132 			info->attrs[ILA_ATTR_LOCATOR]);
133 
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]);
137 
138 	if (info->attrs[ILA_ATTR_CSUM_MODE])
139 		xp->ip.csum_mode = nla_get_u8(info->attrs[ILA_ATTR_CSUM_MODE]);
140 
141 	if (info->attrs[ILA_ATTR_IFINDEX])
142 		xp->ifindex = nla_get_s32(info->attrs[ILA_ATTR_IFINDEX]);
143 
144 	return 0;
145 }
146 
147 /* Must be called with rcu readlock */
148 static inline struct ila_map *ila_lookup_wildcards(struct ila_addr *iaddr,
149 						   int ifindex,
150 						   struct ila_net *ilan)
151 {
152 	struct ila_map *ila;
153 
154 	ila = rhashtable_lookup_fast(&ilan->rhash_table, &iaddr->loc,
155 				     rht_params);
156 	while (ila) {
157 		if (!ila_cmp_wildcards(ila, iaddr, ifindex))
158 			return ila;
159 		ila = rcu_access_pointer(ila->next);
160 	}
161 
162 	return NULL;
163 }
164 
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)
168 {
169 	struct ila_map *ila;
170 
171 	ila = rhashtable_lookup_fast(&ilan->rhash_table,
172 				     &xp->ip.locator_match,
173 				     rht_params);
174 	while (ila) {
175 		if (!ila_cmp_params(ila, xp))
176 			return ila;
177 		ila = rcu_access_pointer(ila->next);
178 	}
179 
180 	return NULL;
181 }
182 
183 static inline void ila_release(struct ila_map *ila)
184 {
185 	kfree_rcu(ila, rcu);
186 }
187 
188 static void ila_free_cb(void *ptr, void *arg)
189 {
190 	struct ila_map *ila = (struct ila_map *)ptr, *next;
191 
192 	/* Assume rcu_readlock held */
193 	while (ila) {
194 		next = rcu_access_pointer(ila->next);
195 		ila_release(ila);
196 		ila = next;
197 	}
198 }
199 
200 static int ila_xlat_addr(struct sk_buff *skb, bool set_csum_neutral);
201 
202 static unsigned int
203 ila_nf_input(void *priv,
204 	     struct sk_buff *skb,
205 	     const struct nf_hook_state *state)
206 {
207 	ila_xlat_addr(skb, false);
208 	return NF_ACCEPT;
209 }
210 
211 static struct nf_hook_ops ila_nf_hook_ops[] __read_mostly = {
212 	{
213 		.hook = ila_nf_input,
214 		.pf = NFPROTO_IPV6,
215 		.hooknum = NF_INET_PRE_ROUTING,
216 		.priority = -1,
217 	},
218 };
219 
220 static int ila_add_mapping(struct net *net, struct ila_xlat_params *xp)
221 {
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);
225 	int err = 0, order;
226 
227 	if (!ilan->hooks_registered) {
228 		/* We defer registering net hooks in the namespace until the
229 		 * first mapping is added.
230 		 */
231 		err = nf_register_net_hooks(net, ila_nf_hook_ops,
232 					    ARRAY_SIZE(ila_nf_hook_ops));
233 		if (err)
234 			return err;
235 
236 		ilan->hooks_registered = true;
237 	}
238 
239 	ila = kzalloc(sizeof(*ila), GFP_KERNEL);
240 	if (!ila)
241 		return -ENOMEM;
242 
243 	ila_init_saved_csum(&xp->ip);
244 
245 	ila->xp = *xp;
246 
247 	order = ila_order(ila);
248 
249 	spin_lock(lock);
250 
251 	head = rhashtable_lookup_fast(&ilan->rhash_table,
252 				      &xp->ip.locator_match,
253 				      rht_params);
254 	if (!head) {
255 		/* New entry for the rhash_table */
256 		err = rhashtable_lookup_insert_fast(&ilan->rhash_table,
257 						    &ila->node, rht_params);
258 	} else {
259 		struct ila_map *tila = head, *prev = NULL;
260 
261 		do {
262 			if (!ila_cmp_params(tila, xp)) {
263 				err = -EEXIST;
264 				goto out;
265 			}
266 
267 			if (order > ila_order(tila))
268 				break;
269 
270 			prev = tila;
271 			tila = rcu_dereference_protected(tila->next,
272 				lockdep_is_held(lock));
273 		} while (tila);
274 
275 		if (prev) {
276 			/* Insert in sub list of head */
277 			RCU_INIT_POINTER(ila->next, tila);
278 			rcu_assign_pointer(prev->next, ila);
279 		} else {
280 			/* Make this ila new head */
281 			RCU_INIT_POINTER(ila->next, head);
282 			err = rhashtable_replace_fast(&ilan->rhash_table,
283 						      &head->node,
284 						      &ila->node, rht_params);
285 			if (err)
286 				goto out;
287 		}
288 	}
289 
290 out:
291 	spin_unlock(lock);
292 
293 	if (err)
294 		kfree(ila);
295 
296 	return err;
297 }
298 
299 static int ila_del_mapping(struct net *net, struct ila_xlat_params *xp)
300 {
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);
304 	int err = -ENOENT;
305 
306 	spin_lock(lock);
307 
308 	head = rhashtable_lookup_fast(&ilan->rhash_table,
309 				      &xp->ip.locator_match, rht_params);
310 	ila = head;
311 
312 	prev = NULL;
313 
314 	while (ila) {
315 		if (ila_cmp_params(ila, xp)) {
316 			prev = ila;
317 			ila = rcu_dereference_protected(ila->next,
318 							lockdep_is_held(lock));
319 			continue;
320 		}
321 
322 		err = 0;
323 
324 		if (prev) {
325 			/* Not head, just delete from list */
326 			rcu_assign_pointer(prev->next, ila->next);
327 		} else {
328 			/* It is the head. If there is something in the
329 			 * sublist we need to make a new head.
330 			 */
331 			head = rcu_dereference_protected(ila->next,
332 							 lockdep_is_held(lock));
333 			if (head) {
334 				/* Put first entry in the sublist into the
335 				 * table
336 				 */
337 				err = rhashtable_replace_fast(
338 					&ilan->rhash_table, &ila->node,
339 					&head->node, rht_params);
340 				if (err)
341 					goto out;
342 			} else {
343 				/* Entry no longer used */
344 				err = rhashtable_remove_fast(&ilan->rhash_table,
345 							     &ila->node,
346 							     rht_params);
347 			}
348 		}
349 
350 		ila_release(ila);
351 
352 		break;
353 	}
354 
355 out:
356 	spin_unlock(lock);
357 
358 	return err;
359 }
360 
361 static int ila_nl_cmd_add_mapping(struct sk_buff *skb, struct genl_info *info)
362 {
363 	struct net *net = genl_info_net(info);
364 	struct ila_xlat_params p;
365 	int err;
366 
367 	err = parse_nl_config(info, &p);
368 	if (err)
369 		return err;
370 
371 	return ila_add_mapping(net, &p);
372 }
373 
374 static int ila_nl_cmd_del_mapping(struct sk_buff *skb, struct genl_info *info)
375 {
376 	struct net *net = genl_info_net(info);
377 	struct ila_xlat_params xp;
378 	int err;
379 
380 	err = parse_nl_config(info, &xp);
381 	if (err)
382 		return err;
383 
384 	ila_del_mapping(net, &xp);
385 
386 	return 0;
387 }
388 
389 static int ila_fill_info(struct ila_map *ila, struct sk_buff *msg)
390 {
391 	if (nla_put_u64_64bit(msg, ILA_ATTR_LOCATOR,
392 			      (__force u64)ila->xp.ip.locator.v64,
393 			      ILA_ATTR_PAD) ||
394 	    nla_put_u64_64bit(msg, ILA_ATTR_LOCATOR_MATCH,
395 			      (__force u64)ila->xp.ip.locator_match.v64,
396 			      ILA_ATTR_PAD) ||
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))
399 		return -1;
400 
401 	return 0;
402 }
403 
404 static int ila_dump_info(struct ila_map *ila,
405 			 u32 portid, u32 seq, u32 flags,
406 			 struct sk_buff *skb, u8 cmd)
407 {
408 	void *hdr;
409 
410 	hdr = genlmsg_put(skb, portid, seq, &ila_nl_family, flags, cmd);
411 	if (!hdr)
412 		return -ENOMEM;
413 
414 	if (ila_fill_info(ila, skb) < 0)
415 		goto nla_put_failure;
416 
417 	genlmsg_end(skb, hdr);
418 	return 0;
419 
420 nla_put_failure:
421 	genlmsg_cancel(skb, hdr);
422 	return -EMSGSIZE;
423 }
424 
425 static int ila_nl_cmd_get_mapping(struct sk_buff *skb, struct genl_info *info)
426 {
427 	struct net *net = genl_info_net(info);
428 	struct ila_net *ilan = net_generic(net, ila_net_id);
429 	struct sk_buff *msg;
430 	struct ila_xlat_params xp;
431 	struct ila_map *ila;
432 	int ret;
433 
434 	ret = parse_nl_config(info, &xp);
435 	if (ret)
436 		return ret;
437 
438 	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
439 	if (!msg)
440 		return -ENOMEM;
441 
442 	rcu_read_lock();
443 
444 	ila = ila_lookup_by_params(&xp, ilan);
445 	if (ila) {
446 		ret = ila_dump_info(ila,
447 				    info->snd_portid,
448 				    info->snd_seq, 0, msg,
449 				    info->genlhdr->cmd);
450 	}
451 
452 	rcu_read_unlock();
453 
454 	if (ret < 0)
455 		goto out_free;
456 
457 	return genlmsg_reply(msg, info);
458 
459 out_free:
460 	nlmsg_free(msg);
461 	return ret;
462 }
463 
464 struct ila_dump_iter {
465 	struct rhashtable_iter rhiter;
466 };
467 
468 static int ila_nl_dump_start(struct netlink_callback *cb)
469 {
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];
473 
474 	if (!iter) {
475 		iter = kmalloc(sizeof(*iter), GFP_KERNEL);
476 		if (!iter)
477 			return -ENOMEM;
478 
479 		cb->args[0] = (long)iter;
480 	}
481 
482 	return rhashtable_walk_init(&ilan->rhash_table, &iter->rhiter,
483 				    GFP_KERNEL);
484 }
485 
486 static int ila_nl_dump_done(struct netlink_callback *cb)
487 {
488 	struct ila_dump_iter *iter = (struct ila_dump_iter *)cb->args[0];
489 
490 	rhashtable_walk_exit(&iter->rhiter);
491 
492 	kfree(iter);
493 
494 	return 0;
495 }
496 
497 static int ila_nl_dump(struct sk_buff *skb, struct netlink_callback *cb)
498 {
499 	struct ila_dump_iter *iter = (struct ila_dump_iter *)cb->args[0];
500 	struct rhashtable_iter *rhiter = &iter->rhiter;
501 	struct ila_map *ila;
502 	int ret;
503 
504 	ret = rhashtable_walk_start(rhiter);
505 	if (ret && ret != -EAGAIN)
506 		goto done;
507 
508 	for (;;) {
509 		ila = rhashtable_walk_next(rhiter);
510 
511 		if (IS_ERR(ila)) {
512 			if (PTR_ERR(ila) == -EAGAIN)
513 				continue;
514 			ret = PTR_ERR(ila);
515 			goto done;
516 		} else if (!ila) {
517 			break;
518 		}
519 
520 		while (ila) {
521 			ret =  ila_dump_info(ila, NETLINK_CB(cb->skb).portid,
522 					     cb->nlh->nlmsg_seq, NLM_F_MULTI,
523 					     skb, ILA_CMD_GET);
524 			if (ret)
525 				goto done;
526 
527 			ila = rcu_access_pointer(ila->next);
528 		}
529 	}
530 
531 	ret = skb->len;
532 
533 done:
534 	rhashtable_walk_stop(rhiter);
535 	return ret;
536 }
537 
538 static const struct genl_ops ila_nl_ops[] = {
539 	{
540 		.cmd = ILA_CMD_ADD,
541 		.doit = ila_nl_cmd_add_mapping,
542 		.policy = ila_nl_policy,
543 		.flags = GENL_ADMIN_PERM,
544 	},
545 	{
546 		.cmd = ILA_CMD_DEL,
547 		.doit = ila_nl_cmd_del_mapping,
548 		.policy = ila_nl_policy,
549 		.flags = GENL_ADMIN_PERM,
550 	},
551 	{
552 		.cmd = ILA_CMD_GET,
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,
558 	},
559 };
560 
561 static struct genl_family ila_nl_family __ro_after_init = {
562 	.hdrsize	= 0,
563 	.name		= ILA_GENL_NAME,
564 	.version	= ILA_GENL_VERSION,
565 	.maxattr	= ILA_ATTR_MAX,
566 	.netnsok	= true,
567 	.parallel_ops	= true,
568 	.module		= THIS_MODULE,
569 	.ops		= ila_nl_ops,
570 	.n_ops		= ARRAY_SIZE(ila_nl_ops),
571 };
572 
573 #define ILA_HASH_TABLE_SIZE 1024
574 
575 static __net_init int ila_init_net(struct net *net)
576 {
577 	int err;
578 	struct ila_net *ilan = net_generic(net, ila_net_id);
579 
580 	err = alloc_ila_locks(ilan);
581 	if (err)
582 		return err;
583 
584 	rhashtable_init(&ilan->rhash_table, &rht_params);
585 
586 	return 0;
587 }
588 
589 static __net_exit void ila_exit_net(struct net *net)
590 {
591 	struct ila_net *ilan = net_generic(net, ila_net_id);
592 
593 	rhashtable_free_and_destroy(&ilan->rhash_table, ila_free_cb, NULL);
594 
595 	kvfree(ilan->locks);
596 
597 	if (ilan->hooks_registered)
598 		nf_unregister_net_hooks(net, ila_nf_hook_ops,
599 					ARRAY_SIZE(ila_nf_hook_ops));
600 }
601 
602 static struct pernet_operations ila_net_ops = {
603 	.init = ila_init_net,
604 	.exit = ila_exit_net,
605 	.id   = &ila_net_id,
606 	.size = sizeof(struct ila_net),
607 };
608 
609 static int ila_xlat_addr(struct sk_buff *skb, bool set_csum_neutral)
610 {
611 	struct ila_map *ila;
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);
616 
617 	/* Assumes skb contains a valid IPv6 header that is pulled */
618 
619 	if (!ila_addr_is_ila(iaddr)) {
620 		/* Type indicates this is not an ILA address */
621 		return 0;
622 	}
623 
624 	rcu_read_lock();
625 
626 	ila = ila_lookup_wildcards(iaddr, skb->dev->ifindex, ilan);
627 	if (ila)
628 		ila_update_ipv6_locator(skb, &ila->xp.ip, set_csum_neutral);
629 
630 	rcu_read_unlock();
631 
632 	return 0;
633 }
634 
635 int __init ila_xlat_init(void)
636 {
637 	int ret;
638 
639 	ret = register_pernet_device(&ila_net_ops);
640 	if (ret)
641 		goto exit;
642 
643 	ret = genl_register_family(&ila_nl_family);
644 	if (ret < 0)
645 		goto unregister;
646 
647 	return 0;
648 
649 unregister:
650 	unregister_pernet_device(&ila_net_ops);
651 exit:
652 	return ret;
653 }
654 
655 void ila_xlat_fini(void)
656 {
657 	genl_unregister_family(&ila_nl_family);
658 	unregister_pernet_device(&ila_net_ops);
659 }
660