ila_xlat.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653
  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. struct ila_xlat_params {
  12. struct ila_params ip;
  13. int ifindex;
  14. };
  15. struct ila_map {
  16. struct ila_xlat_params xp;
  17. struct rhash_head node;
  18. struct ila_map __rcu *next;
  19. struct rcu_head rcu;
  20. };
  21. static unsigned int ila_net_id;
  22. struct ila_net {
  23. struct rhashtable rhash_table;
  24. spinlock_t *locks; /* Bucket locks for entry manipulation */
  25. unsigned int locks_mask;
  26. bool hooks_registered;
  27. };
  28. #define LOCKS_PER_CPU 10
  29. static int alloc_ila_locks(struct ila_net *ilan)
  30. {
  31. unsigned int i, size;
  32. unsigned int nr_pcpus = num_possible_cpus();
  33. nr_pcpus = min_t(unsigned int, nr_pcpus, 32UL);
  34. size = roundup_pow_of_two(nr_pcpus * LOCKS_PER_CPU);
  35. if (sizeof(spinlock_t) != 0) {
  36. #ifdef CONFIG_NUMA
  37. if (size * sizeof(spinlock_t) > PAGE_SIZE)
  38. ilan->locks = vmalloc(size * sizeof(spinlock_t));
  39. else
  40. #endif
  41. ilan->locks = kmalloc_array(size, sizeof(spinlock_t),
  42. GFP_KERNEL);
  43. if (!ilan->locks)
  44. return -ENOMEM;
  45. for (i = 0; i < size; i++)
  46. spin_lock_init(&ilan->locks[i]);
  47. }
  48. ilan->locks_mask = size - 1;
  49. return 0;
  50. }
  51. static u32 hashrnd __read_mostly;
  52. static __always_inline void __ila_hash_secret_init(void)
  53. {
  54. net_get_random_once(&hashrnd, sizeof(hashrnd));
  55. }
  56. static inline u32 ila_locator_hash(struct ila_locator loc)
  57. {
  58. u32 *v = (u32 *)loc.v32;
  59. __ila_hash_secret_init();
  60. return jhash_2words(v[0], v[1], hashrnd);
  61. }
  62. static inline spinlock_t *ila_get_lock(struct ila_net *ilan,
  63. struct ila_locator loc)
  64. {
  65. return &ilan->locks[ila_locator_hash(loc) & ilan->locks_mask];
  66. }
  67. static inline int ila_cmp_wildcards(struct ila_map *ila,
  68. struct ila_addr *iaddr, int ifindex)
  69. {
  70. return (ila->xp.ifindex && ila->xp.ifindex != ifindex);
  71. }
  72. static inline int ila_cmp_params(struct ila_map *ila,
  73. struct ila_xlat_params *xp)
  74. {
  75. return (ila->xp.ifindex != xp->ifindex);
  76. }
  77. static int ila_cmpfn(struct rhashtable_compare_arg *arg,
  78. const void *obj)
  79. {
  80. const struct ila_map *ila = obj;
  81. return (ila->xp.ip.locator_match.v64 != *(__be64 *)arg->key);
  82. }
  83. static inline int ila_order(struct ila_map *ila)
  84. {
  85. int score = 0;
  86. if (ila->xp.ifindex)
  87. score += 1 << 1;
  88. return score;
  89. }
  90. static const struct rhashtable_params rht_params = {
  91. .nelem_hint = 1024,
  92. .head_offset = offsetof(struct ila_map, node),
  93. .key_offset = offsetof(struct ila_map, xp.ip.locator_match),
  94. .key_len = sizeof(u64), /* identifier */
  95. .max_size = 1048576,
  96. .min_size = 256,
  97. .automatic_shrinking = true,
  98. .obj_cmpfn = ila_cmpfn,
  99. };
  100. static struct genl_family ila_nl_family = {
  101. .id = GENL_ID_GENERATE,
  102. .hdrsize = 0,
  103. .name = ILA_GENL_NAME,
  104. .version = ILA_GENL_VERSION,
  105. .maxattr = ILA_ATTR_MAX,
  106. .netnsok = true,
  107. .parallel_ops = true,
  108. };
  109. static const struct nla_policy ila_nl_policy[ILA_ATTR_MAX + 1] = {
  110. [ILA_ATTR_LOCATOR] = { .type = NLA_U64, },
  111. [ILA_ATTR_LOCATOR_MATCH] = { .type = NLA_U64, },
  112. [ILA_ATTR_IFINDEX] = { .type = NLA_U32, },
  113. [ILA_ATTR_CSUM_MODE] = { .type = NLA_U8, },
  114. };
  115. static int parse_nl_config(struct genl_info *info,
  116. struct ila_xlat_params *xp)
  117. {
  118. memset(xp, 0, sizeof(*xp));
  119. if (info->attrs[ILA_ATTR_LOCATOR])
  120. xp->ip.locator.v64 = (__force __be64)nla_get_u64(
  121. info->attrs[ILA_ATTR_LOCATOR]);
  122. if (info->attrs[ILA_ATTR_LOCATOR_MATCH])
  123. xp->ip.locator_match.v64 = (__force __be64)nla_get_u64(
  124. info->attrs[ILA_ATTR_LOCATOR_MATCH]);
  125. if (info->attrs[ILA_ATTR_CSUM_MODE])
  126. xp->ip.csum_mode = nla_get_u8(info->attrs[ILA_ATTR_CSUM_MODE]);
  127. if (info->attrs[ILA_ATTR_IFINDEX])
  128. xp->ifindex = nla_get_s32(info->attrs[ILA_ATTR_IFINDEX]);
  129. return 0;
  130. }
  131. /* Must be called with rcu readlock */
  132. static inline struct ila_map *ila_lookup_wildcards(struct ila_addr *iaddr,
  133. int ifindex,
  134. struct ila_net *ilan)
  135. {
  136. struct ila_map *ila;
  137. ila = rhashtable_lookup_fast(&ilan->rhash_table, &iaddr->loc,
  138. rht_params);
  139. while (ila) {
  140. if (!ila_cmp_wildcards(ila, iaddr, ifindex))
  141. return ila;
  142. ila = rcu_access_pointer(ila->next);
  143. }
  144. return NULL;
  145. }
  146. /* Must be called with rcu readlock */
  147. static inline struct ila_map *ila_lookup_by_params(struct ila_xlat_params *xp,
  148. struct ila_net *ilan)
  149. {
  150. struct ila_map *ila;
  151. ila = rhashtable_lookup_fast(&ilan->rhash_table,
  152. &xp->ip.locator_match,
  153. rht_params);
  154. while (ila) {
  155. if (!ila_cmp_params(ila, xp))
  156. return ila;
  157. ila = rcu_access_pointer(ila->next);
  158. }
  159. return NULL;
  160. }
  161. static inline void ila_release(struct ila_map *ila)
  162. {
  163. kfree_rcu(ila, rcu);
  164. }
  165. static void ila_free_cb(void *ptr, void *arg)
  166. {
  167. struct ila_map *ila = (struct ila_map *)ptr, *next;
  168. /* Assume rcu_readlock held */
  169. while (ila) {
  170. next = rcu_access_pointer(ila->next);
  171. ila_release(ila);
  172. ila = next;
  173. }
  174. }
  175. static int ila_xlat_addr(struct sk_buff *skb, bool set_csum_neutral);
  176. static unsigned int
  177. ila_nf_input(void *priv,
  178. struct sk_buff *skb,
  179. const struct nf_hook_state *state)
  180. {
  181. ila_xlat_addr(skb, false);
  182. return NF_ACCEPT;
  183. }
  184. static struct nf_hook_ops ila_nf_hook_ops[] __read_mostly = {
  185. {
  186. .hook = ila_nf_input,
  187. .pf = NFPROTO_IPV6,
  188. .hooknum = NF_INET_PRE_ROUTING,
  189. .priority = -1,
  190. },
  191. };
  192. static int ila_add_mapping(struct net *net, struct ila_xlat_params *xp)
  193. {
  194. struct ila_net *ilan = net_generic(net, ila_net_id);
  195. struct ila_map *ila, *head;
  196. spinlock_t *lock = ila_get_lock(ilan, xp->ip.locator_match);
  197. int err = 0, order;
  198. if (!ilan->hooks_registered) {
  199. /* We defer registering net hooks in the namespace until the
  200. * first mapping is added.
  201. */
  202. err = nf_register_net_hooks(net, ila_nf_hook_ops,
  203. ARRAY_SIZE(ila_nf_hook_ops));
  204. if (err)
  205. return err;
  206. ilan->hooks_registered = true;
  207. }
  208. ila = kzalloc(sizeof(*ila), GFP_KERNEL);
  209. if (!ila)
  210. return -ENOMEM;
  211. ila_init_saved_csum(&xp->ip);
  212. ila->xp = *xp;
  213. order = ila_order(ila);
  214. spin_lock(lock);
  215. head = rhashtable_lookup_fast(&ilan->rhash_table,
  216. &xp->ip.locator_match,
  217. rht_params);
  218. if (!head) {
  219. /* New entry for the rhash_table */
  220. err = rhashtable_lookup_insert_fast(&ilan->rhash_table,
  221. &ila->node, rht_params);
  222. } else {
  223. struct ila_map *tila = head, *prev = NULL;
  224. do {
  225. if (!ila_cmp_params(tila, xp)) {
  226. err = -EEXIST;
  227. goto out;
  228. }
  229. if (order > ila_order(tila))
  230. break;
  231. prev = tila;
  232. tila = rcu_dereference_protected(tila->next,
  233. lockdep_is_held(lock));
  234. } while (tila);
  235. if (prev) {
  236. /* Insert in sub list of head */
  237. RCU_INIT_POINTER(ila->next, tila);
  238. rcu_assign_pointer(prev->next, ila);
  239. } else {
  240. /* Make this ila new head */
  241. RCU_INIT_POINTER(ila->next, head);
  242. err = rhashtable_replace_fast(&ilan->rhash_table,
  243. &head->node,
  244. &ila->node, rht_params);
  245. if (err)
  246. goto out;
  247. }
  248. }
  249. out:
  250. spin_unlock(lock);
  251. if (err)
  252. kfree(ila);
  253. return err;
  254. }
  255. static int ila_del_mapping(struct net *net, struct ila_xlat_params *xp)
  256. {
  257. struct ila_net *ilan = net_generic(net, ila_net_id);
  258. struct ila_map *ila, *head, *prev;
  259. spinlock_t *lock = ila_get_lock(ilan, xp->ip.locator_match);
  260. int err = -ENOENT;
  261. spin_lock(lock);
  262. head = rhashtable_lookup_fast(&ilan->rhash_table,
  263. &xp->ip.locator_match, rht_params);
  264. ila = head;
  265. prev = NULL;
  266. while (ila) {
  267. if (ila_cmp_params(ila, xp)) {
  268. prev = ila;
  269. ila = rcu_dereference_protected(ila->next,
  270. lockdep_is_held(lock));
  271. continue;
  272. }
  273. err = 0;
  274. if (prev) {
  275. /* Not head, just delete from list */
  276. rcu_assign_pointer(prev->next, ila->next);
  277. } else {
  278. /* It is the head. If there is something in the
  279. * sublist we need to make a new head.
  280. */
  281. head = rcu_dereference_protected(ila->next,
  282. lockdep_is_held(lock));
  283. if (head) {
  284. /* Put first entry in the sublist into the
  285. * table
  286. */
  287. err = rhashtable_replace_fast(
  288. &ilan->rhash_table, &ila->node,
  289. &head->node, rht_params);
  290. if (err)
  291. goto out;
  292. } else {
  293. /* Entry no longer used */
  294. err = rhashtable_remove_fast(&ilan->rhash_table,
  295. &ila->node,
  296. rht_params);
  297. }
  298. }
  299. ila_release(ila);
  300. break;
  301. }
  302. out:
  303. spin_unlock(lock);
  304. return err;
  305. }
  306. static int ila_nl_cmd_add_mapping(struct sk_buff *skb, struct genl_info *info)
  307. {
  308. struct net *net = genl_info_net(info);
  309. struct ila_xlat_params p;
  310. int err;
  311. err = parse_nl_config(info, &p);
  312. if (err)
  313. return err;
  314. return ila_add_mapping(net, &p);
  315. }
  316. static int ila_nl_cmd_del_mapping(struct sk_buff *skb, struct genl_info *info)
  317. {
  318. struct net *net = genl_info_net(info);
  319. struct ila_xlat_params xp;
  320. int err;
  321. err = parse_nl_config(info, &xp);
  322. if (err)
  323. return err;
  324. ila_del_mapping(net, &xp);
  325. return 0;
  326. }
  327. static int ila_fill_info(struct ila_map *ila, struct sk_buff *msg)
  328. {
  329. if (nla_put_u64_64bit(msg, ILA_ATTR_LOCATOR,
  330. (__force u64)ila->xp.ip.locator.v64,
  331. ILA_ATTR_PAD) ||
  332. nla_put_u64_64bit(msg, ILA_ATTR_LOCATOR_MATCH,
  333. (__force u64)ila->xp.ip.locator_match.v64,
  334. ILA_ATTR_PAD) ||
  335. nla_put_s32(msg, ILA_ATTR_IFINDEX, ila->xp.ifindex) ||
  336. nla_put_u32(msg, ILA_ATTR_CSUM_MODE, ila->xp.ip.csum_mode))
  337. return -1;
  338. return 0;
  339. }
  340. static int ila_dump_info(struct ila_map *ila,
  341. u32 portid, u32 seq, u32 flags,
  342. struct sk_buff *skb, u8 cmd)
  343. {
  344. void *hdr;
  345. hdr = genlmsg_put(skb, portid, seq, &ila_nl_family, flags, cmd);
  346. if (!hdr)
  347. return -ENOMEM;
  348. if (ila_fill_info(ila, skb) < 0)
  349. goto nla_put_failure;
  350. genlmsg_end(skb, hdr);
  351. return 0;
  352. nla_put_failure:
  353. genlmsg_cancel(skb, hdr);
  354. return -EMSGSIZE;
  355. }
  356. static int ila_nl_cmd_get_mapping(struct sk_buff *skb, struct genl_info *info)
  357. {
  358. struct net *net = genl_info_net(info);
  359. struct ila_net *ilan = net_generic(net, ila_net_id);
  360. struct sk_buff *msg;
  361. struct ila_xlat_params xp;
  362. struct ila_map *ila;
  363. int ret;
  364. ret = parse_nl_config(info, &xp);
  365. if (ret)
  366. return ret;
  367. msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
  368. if (!msg)
  369. return -ENOMEM;
  370. rcu_read_lock();
  371. ila = ila_lookup_by_params(&xp, ilan);
  372. if (ila) {
  373. ret = ila_dump_info(ila,
  374. info->snd_portid,
  375. info->snd_seq, 0, msg,
  376. info->genlhdr->cmd);
  377. }
  378. rcu_read_unlock();
  379. if (ret < 0)
  380. goto out_free;
  381. return genlmsg_reply(msg, info);
  382. out_free:
  383. nlmsg_free(msg);
  384. return ret;
  385. }
  386. struct ila_dump_iter {
  387. struct rhashtable_iter rhiter;
  388. };
  389. static int ila_nl_dump_start(struct netlink_callback *cb)
  390. {
  391. struct net *net = sock_net(cb->skb->sk);
  392. struct ila_net *ilan = net_generic(net, ila_net_id);
  393. struct ila_dump_iter *iter = (struct ila_dump_iter *)cb->args;
  394. return rhashtable_walk_init(&ilan->rhash_table, &iter->rhiter,
  395. GFP_KERNEL);
  396. }
  397. static int ila_nl_dump_done(struct netlink_callback *cb)
  398. {
  399. struct ila_dump_iter *iter = (struct ila_dump_iter *)cb->args;
  400. rhashtable_walk_exit(&iter->rhiter);
  401. return 0;
  402. }
  403. static int ila_nl_dump(struct sk_buff *skb, struct netlink_callback *cb)
  404. {
  405. struct ila_dump_iter *iter = (struct ila_dump_iter *)cb->args;
  406. struct rhashtable_iter *rhiter = &iter->rhiter;
  407. struct ila_map *ila;
  408. int ret;
  409. ret = rhashtable_walk_start(rhiter);
  410. if (ret && ret != -EAGAIN)
  411. goto done;
  412. for (;;) {
  413. ila = rhashtable_walk_next(rhiter);
  414. if (IS_ERR(ila)) {
  415. if (PTR_ERR(ila) == -EAGAIN)
  416. continue;
  417. ret = PTR_ERR(ila);
  418. goto done;
  419. } else if (!ila) {
  420. break;
  421. }
  422. while (ila) {
  423. ret = ila_dump_info(ila, NETLINK_CB(cb->skb).portid,
  424. cb->nlh->nlmsg_seq, NLM_F_MULTI,
  425. skb, ILA_CMD_GET);
  426. if (ret)
  427. goto done;
  428. ila = rcu_access_pointer(ila->next);
  429. }
  430. }
  431. ret = skb->len;
  432. done:
  433. rhashtable_walk_stop(rhiter);
  434. return ret;
  435. }
  436. static const struct genl_ops ila_nl_ops[] = {
  437. {
  438. .cmd = ILA_CMD_ADD,
  439. .doit = ila_nl_cmd_add_mapping,
  440. .policy = ila_nl_policy,
  441. .flags = GENL_ADMIN_PERM,
  442. },
  443. {
  444. .cmd = ILA_CMD_DEL,
  445. .doit = ila_nl_cmd_del_mapping,
  446. .policy = ila_nl_policy,
  447. .flags = GENL_ADMIN_PERM,
  448. },
  449. {
  450. .cmd = ILA_CMD_GET,
  451. .doit = ila_nl_cmd_get_mapping,
  452. .start = ila_nl_dump_start,
  453. .dumpit = ila_nl_dump,
  454. .done = ila_nl_dump_done,
  455. .policy = ila_nl_policy,
  456. },
  457. };
  458. #define ILA_HASH_TABLE_SIZE 1024
  459. static __net_init int ila_init_net(struct net *net)
  460. {
  461. int err;
  462. struct ila_net *ilan = net_generic(net, ila_net_id);
  463. err = alloc_ila_locks(ilan);
  464. if (err)
  465. return err;
  466. rhashtable_init(&ilan->rhash_table, &rht_params);
  467. return 0;
  468. }
  469. static __net_exit void ila_exit_net(struct net *net)
  470. {
  471. struct ila_net *ilan = net_generic(net, ila_net_id);
  472. rhashtable_free_and_destroy(&ilan->rhash_table, ila_free_cb, NULL);
  473. kvfree(ilan->locks);
  474. if (ilan->hooks_registered)
  475. nf_unregister_net_hooks(net, ila_nf_hook_ops,
  476. ARRAY_SIZE(ila_nf_hook_ops));
  477. }
  478. static struct pernet_operations ila_net_ops = {
  479. .init = ila_init_net,
  480. .exit = ila_exit_net,
  481. .id = &ila_net_id,
  482. .size = sizeof(struct ila_net),
  483. };
  484. static int ila_xlat_addr(struct sk_buff *skb, bool set_csum_neutral)
  485. {
  486. struct ila_map *ila;
  487. struct ipv6hdr *ip6h = ipv6_hdr(skb);
  488. struct net *net = dev_net(skb->dev);
  489. struct ila_net *ilan = net_generic(net, ila_net_id);
  490. struct ila_addr *iaddr = ila_a2i(&ip6h->daddr);
  491. /* Assumes skb contains a valid IPv6 header that is pulled */
  492. if (!ila_addr_is_ila(iaddr)) {
  493. /* Type indicates this is not an ILA address */
  494. return 0;
  495. }
  496. rcu_read_lock();
  497. ila = ila_lookup_wildcards(iaddr, skb->dev->ifindex, ilan);
  498. if (ila)
  499. ila_update_ipv6_locator(skb, &ila->xp.ip, set_csum_neutral);
  500. rcu_read_unlock();
  501. return 0;
  502. }
  503. int ila_xlat_init(void)
  504. {
  505. int ret;
  506. ret = register_pernet_device(&ila_net_ops);
  507. if (ret)
  508. goto exit;
  509. ret = genl_register_family_with_ops(&ila_nl_family,
  510. ila_nl_ops);
  511. if (ret < 0)
  512. goto unregister;
  513. return 0;
  514. unregister:
  515. unregister_pernet_device(&ila_net_ops);
  516. exit:
  517. return ret;
  518. }
  519. void ila_xlat_fini(void)
  520. {
  521. genl_unregister_family(&ila_nl_family);
  522. unregister_pernet_device(&ila_net_ops);
  523. }