ipvlan_l3s.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /* Copyright (c) 2014 Mahesh Bandewar <maheshb@google.com>
  3. */
  4. #include "ipvlan.h"
  5. static unsigned int ipvlan_netid __read_mostly;
  6. struct ipvlan_netns {
  7. unsigned int ipvl_nf_hook_refcnt;
  8. };
  9. static struct ipvl_addr *ipvlan_skb_to_addr(struct sk_buff *skb,
  10. struct net_device *dev)
  11. {
  12. struct ipvl_addr *addr = NULL;
  13. struct ipvl_port *port;
  14. int addr_type;
  15. void *lyr3h;
  16. if (!dev || !netif_is_ipvlan_port(dev))
  17. goto out;
  18. port = ipvlan_port_get_rcu(dev);
  19. if (!port || port->mode != IPVLAN_MODE_L3S)
  20. goto out;
  21. lyr3h = ipvlan_get_L3_hdr(port, skb, &addr_type);
  22. if (!lyr3h)
  23. goto out;
  24. addr = ipvlan_addr_lookup(port, lyr3h, addr_type, true);
  25. out:
  26. return addr;
  27. }
  28. static struct sk_buff *ipvlan_l3_rcv(struct net_device *dev,
  29. struct sk_buff *skb, u16 proto)
  30. {
  31. struct ipvl_addr *addr;
  32. struct net_device *sdev;
  33. addr = ipvlan_skb_to_addr(skb, dev);
  34. if (!addr)
  35. goto out;
  36. sdev = addr->master->dev;
  37. switch (proto) {
  38. case AF_INET:
  39. {
  40. struct iphdr *ip4h = ip_hdr(skb);
  41. int err;
  42. err = ip_route_input_noref(skb, ip4h->daddr, ip4h->saddr,
  43. ip4h->tos, sdev);
  44. if (unlikely(err))
  45. goto out;
  46. break;
  47. }
  48. #if IS_ENABLED(CONFIG_IPV6)
  49. case AF_INET6:
  50. {
  51. struct dst_entry *dst;
  52. struct ipv6hdr *ip6h = ipv6_hdr(skb);
  53. int flags = RT6_LOOKUP_F_HAS_SADDR;
  54. struct flowi6 fl6 = {
  55. .flowi6_iif = sdev->ifindex,
  56. .daddr = ip6h->daddr,
  57. .saddr = ip6h->saddr,
  58. .flowlabel = ip6_flowinfo(ip6h),
  59. .flowi6_mark = skb->mark,
  60. .flowi6_proto = ip6h->nexthdr,
  61. };
  62. skb_dst_drop(skb);
  63. dst = ip6_route_input_lookup(dev_net(sdev), sdev, &fl6,
  64. skb, flags);
  65. skb_dst_set(skb, dst);
  66. break;
  67. }
  68. #endif
  69. default:
  70. break;
  71. }
  72. out:
  73. return skb;
  74. }
  75. static const struct l3mdev_ops ipvl_l3mdev_ops = {
  76. .l3mdev_l3_rcv = ipvlan_l3_rcv,
  77. };
  78. static unsigned int ipvlan_nf_input(void *priv, struct sk_buff *skb,
  79. const struct nf_hook_state *state)
  80. {
  81. struct ipvl_addr *addr;
  82. unsigned int len;
  83. addr = ipvlan_skb_to_addr(skb, skb->dev);
  84. if (!addr)
  85. goto out;
  86. skb->dev = addr->master->dev;
  87. len = skb->len + ETH_HLEN;
  88. ipvlan_count_rx(addr->master, len, true, false);
  89. out:
  90. return NF_ACCEPT;
  91. }
  92. static const struct nf_hook_ops ipvl_nfops[] = {
  93. {
  94. .hook = ipvlan_nf_input,
  95. .pf = NFPROTO_IPV4,
  96. .hooknum = NF_INET_LOCAL_IN,
  97. .priority = INT_MAX,
  98. },
  99. #if IS_ENABLED(CONFIG_IPV6)
  100. {
  101. .hook = ipvlan_nf_input,
  102. .pf = NFPROTO_IPV6,
  103. .hooknum = NF_INET_LOCAL_IN,
  104. .priority = INT_MAX,
  105. },
  106. #endif
  107. };
  108. static int ipvlan_register_nf_hook(struct net *net)
  109. {
  110. struct ipvlan_netns *vnet = net_generic(net, ipvlan_netid);
  111. int err = 0;
  112. if (!vnet->ipvl_nf_hook_refcnt) {
  113. err = nf_register_net_hooks(net, ipvl_nfops,
  114. ARRAY_SIZE(ipvl_nfops));
  115. if (!err)
  116. vnet->ipvl_nf_hook_refcnt = 1;
  117. } else {
  118. vnet->ipvl_nf_hook_refcnt++;
  119. }
  120. return err;
  121. }
  122. static void ipvlan_unregister_nf_hook(struct net *net)
  123. {
  124. struct ipvlan_netns *vnet = net_generic(net, ipvlan_netid);
  125. if (WARN_ON(!vnet->ipvl_nf_hook_refcnt))
  126. return;
  127. vnet->ipvl_nf_hook_refcnt--;
  128. if (!vnet->ipvl_nf_hook_refcnt)
  129. nf_unregister_net_hooks(net, ipvl_nfops,
  130. ARRAY_SIZE(ipvl_nfops));
  131. }
  132. void ipvlan_migrate_l3s_hook(struct net *oldnet, struct net *newnet)
  133. {
  134. struct ipvlan_netns *old_vnet;
  135. ASSERT_RTNL();
  136. old_vnet = net_generic(oldnet, ipvlan_netid);
  137. if (!old_vnet->ipvl_nf_hook_refcnt)
  138. return;
  139. ipvlan_register_nf_hook(newnet);
  140. ipvlan_unregister_nf_hook(oldnet);
  141. }
  142. static void ipvlan_ns_exit(struct net *net)
  143. {
  144. struct ipvlan_netns *vnet = net_generic(net, ipvlan_netid);
  145. if (WARN_ON_ONCE(vnet->ipvl_nf_hook_refcnt)) {
  146. vnet->ipvl_nf_hook_refcnt = 0;
  147. nf_unregister_net_hooks(net, ipvl_nfops,
  148. ARRAY_SIZE(ipvl_nfops));
  149. }
  150. }
  151. static struct pernet_operations ipvlan_net_ops = {
  152. .id = &ipvlan_netid,
  153. .size = sizeof(struct ipvlan_netns),
  154. .exit = ipvlan_ns_exit,
  155. };
  156. int ipvlan_l3s_init(void)
  157. {
  158. return register_pernet_subsys(&ipvlan_net_ops);
  159. }
  160. void ipvlan_l3s_cleanup(void)
  161. {
  162. unregister_pernet_subsys(&ipvlan_net_ops);
  163. }
  164. int ipvlan_l3s_register(struct ipvl_port *port)
  165. {
  166. struct net_device *dev = port->dev;
  167. int ret;
  168. ASSERT_RTNL();
  169. ret = ipvlan_register_nf_hook(read_pnet(&port->pnet));
  170. if (!ret) {
  171. dev->l3mdev_ops = &ipvl_l3mdev_ops;
  172. dev->priv_flags |= IFF_L3MDEV_RX_HANDLER;
  173. }
  174. return ret;
  175. }
  176. void ipvlan_l3s_unregister(struct ipvl_port *port)
  177. {
  178. struct net_device *dev = port->dev;
  179. ASSERT_RTNL();
  180. dev->priv_flags &= ~IFF_L3MDEV_RX_HANDLER;
  181. ipvlan_unregister_nf_hook(read_pnet(&port->pnet));
  182. dev->l3mdev_ops = NULL;
  183. }