vxlan.c 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Copyright (C) 2022 Felix Fietkau <nbd@nbd.name>
  4. */
  5. #define _GNU_SOURCE
  6. #include <sys/types.h>
  7. #include <sys/socket.h>
  8. #include <netlink/msg.h>
  9. #include <netlink/attr.h>
  10. #include <netlink/socket.h>
  11. #include <netinet/if_ether.h>
  12. #include <net/if.h>
  13. #include <linux/rtnetlink.h>
  14. #include <linux/ipv6.h>
  15. #include <linux/udp.h>
  16. #include "unetd.h"
  17. struct vxlan_tunnel {
  18. struct network *net;
  19. struct network_service *s;
  20. char ifname[IFNAMSIZ + 1];
  21. int ifindex;
  22. uint16_t mtu;
  23. uint16_t port;
  24. uint32_t vni;
  25. uint32_t *forward_ports;
  26. uint32_t *cur_forward_ports;
  27. bool active;
  28. };
  29. static uint32_t
  30. vxlan_tunnel_id(struct vxlan_tunnel *vt)
  31. {
  32. siphash_key_t key = {};
  33. const char *name = network_service_name(vt->s);
  34. uint64_t val;
  35. if (vt->vni != ~0)
  36. return vt->vni;
  37. siphash_to_le64(&val, name, strlen(name), &key);
  38. return val & 0x00ffffff;
  39. }
  40. static struct nl_msg *vxlan_rtnl_msg(const char *ifname, int type, int flags)
  41. {
  42. struct ifinfomsg iim = {
  43. .ifi_family = AF_UNSPEC,
  44. };
  45. struct nl_msg *msg;
  46. msg = nlmsg_alloc_simple(type, flags | NLM_F_REQUEST);
  47. if (!msg)
  48. return NULL;
  49. nlmsg_append(msg, &iim, sizeof(iim), 0);
  50. nla_put_string(msg, IFLA_IFNAME, ifname);
  51. return msg;
  52. }
  53. static int
  54. vxlan_update_host_fdb_entry(struct vxlan_tunnel *vt, struct network_host *host, bool add)
  55. {
  56. struct ndmsg ndmsg = {
  57. .ndm_family = PF_BRIDGE,
  58. .ndm_state = NUD_NOARP | NUD_PERMANENT,
  59. .ndm_flags = NTF_SELF,
  60. .ndm_ifindex = vt->ifindex,
  61. };
  62. unsigned int flags = NLM_F_REQUEST;
  63. uint8_t lladdr[ETH_ALEN] = {};
  64. struct nl_msg *msg;
  65. if (add)
  66. flags |= NLM_F_CREATE | NLM_F_APPEND;
  67. msg = nlmsg_alloc_simple(add ? RTM_NEWNEIGH : RTM_DELNEIGH, flags);
  68. nlmsg_append(msg, &ndmsg, sizeof(ndmsg), 0);
  69. nla_put(msg, NDA_LLADDR, ETH_ALEN, lladdr);
  70. nla_put(msg, NDA_DST, sizeof(struct in6_addr), &host->peer.local_addr);
  71. nla_put_u32(msg, NDA_IFINDEX, vt->net->ifindex);
  72. return rtnl_call(msg);
  73. }
  74. static void
  75. vxlan_update_fdb_hosts(struct vxlan_tunnel *vt)
  76. {
  77. struct network_service *s = vt->s;
  78. bool active;
  79. int i;
  80. if (!vt->active)
  81. return;
  82. for (i = 0; i < s->n_members; i++) {
  83. if (s->members[i] == vt->net->net_config.local_host)
  84. continue;
  85. if (vt->forward_ports && !bitmask_test(vt->forward_ports, i))
  86. continue;
  87. active = s->members[i]->peer.state.connected;
  88. if (active == bitmask_test(vt->cur_forward_ports, i))
  89. continue;
  90. if (!vxlan_update_host_fdb_entry(vt, s->members[i], active))
  91. bitmask_set_val(vt->cur_forward_ports, i, active);
  92. }
  93. }
  94. static void
  95. vxlan_peer_update(struct network *net, struct network_service *s, struct network_peer *peer)
  96. {
  97. if (!s->vxlan)
  98. return;
  99. vxlan_update_fdb_hosts(s->vxlan);
  100. }
  101. static void
  102. vxlan_tunnel_init(struct vxlan_tunnel *vt)
  103. {
  104. struct network_peer *local = &vt->net->net_config.local_host->peer;
  105. struct nlattr *linkinfo, *data;
  106. struct nl_msg *msg;
  107. struct in6_addr group_addr;
  108. int mtu;
  109. if (rtnl_init())
  110. return;
  111. memset(&group_addr, 0xff, sizeof(group_addr));
  112. msg = vxlan_rtnl_msg(vt->ifname, RTM_NEWLINK, NLM_F_CREATE | NLM_F_EXCL);
  113. linkinfo = nla_nest_start(msg, IFLA_LINKINFO);
  114. nla_put_string(msg, IFLA_INFO_KIND, "vxlan");
  115. nla_put_u32(msg, IFLA_MTU, vt->mtu);
  116. data = nla_nest_start(msg, IFLA_INFO_DATA);
  117. nla_put_u32(msg, IFLA_VXLAN_ID, vxlan_tunnel_id(vt));
  118. nla_put(msg, IFLA_VXLAN_LOCAL6, sizeof(struct in6_addr), &local->local_addr);
  119. nla_put(msg, IFLA_VXLAN_GROUP6, sizeof(struct in6_addr), &group_addr);
  120. nla_put_u16(msg, IFLA_VXLAN_PORT, htons(vt->port));
  121. nla_put_u8(msg, IFLA_VXLAN_LEARNING, 1);
  122. nla_put_u32(msg, IFLA_VXLAN_LINK, vt->net->ifindex);
  123. nla_nest_end(msg, data);
  124. nla_nest_end(msg, linkinfo);
  125. if (rtnl_call(msg) < 0)
  126. return;
  127. vt->ifindex = if_nametoindex(vt->ifname);
  128. if (!vt->ifindex) {
  129. D_SERVICE(vt->net, vt->s, "failed to get ifindex for device %s", vt->ifname);
  130. return;
  131. }
  132. vt->active = true;
  133. vxlan_update_fdb_hosts(vt);
  134. mtu = 1420 - sizeof(struct ipv6hdr) - sizeof(struct udphdr) - 8;
  135. unetd_attach_mssfix(vt->ifindex, mtu);
  136. }
  137. static void
  138. vxlan_tunnel_teardown(struct vxlan_tunnel *vt)
  139. {
  140. struct nl_msg *msg;
  141. vt->active = false;
  142. msg = vxlan_rtnl_msg(vt->ifname, RTM_DELLINK, 0);
  143. rtnl_call(msg);
  144. }
  145. static const char *
  146. vxlan_find_ifname(struct network *net, const char *service)
  147. {
  148. struct blob_attr *cur;
  149. int rem;
  150. if (!net->config.tunnels)
  151. return NULL;
  152. blobmsg_for_each_attr(cur, net->config.tunnels, rem) {
  153. const char *name;
  154. if (!blobmsg_check_attr(cur, true) ||
  155. blobmsg_type(cur) != BLOBMSG_TYPE_STRING)
  156. continue;
  157. if (strcmp(blobmsg_get_string(cur), service) != 0)
  158. continue;
  159. name = blobmsg_name(cur);
  160. if (strlen(name) > IFNAMSIZ)
  161. break;
  162. return name;
  163. }
  164. return NULL;
  165. }
  166. static void
  167. __vxlan_mark_forward_host(struct vxlan_tunnel *vt, struct network_host *host)
  168. {
  169. struct network_service *s = vt->s;
  170. unsigned int i;
  171. for (i = 0; i < s->n_members; i++) {
  172. if (s->members[i] != host)
  173. continue;
  174. bitmask_set(vt->forward_ports, i);
  175. break;
  176. }
  177. }
  178. static void
  179. vxlan_mark_forward_host(struct vxlan_tunnel *vt, const char *name)
  180. {
  181. struct network *net = vt->net;
  182. struct network_host *host;
  183. host = avl_find_element(&net->hosts, name, host, node);
  184. if (!host)
  185. return;
  186. __vxlan_mark_forward_host(vt, host);
  187. }
  188. static void
  189. vxlan_mark_forward_group(struct vxlan_tunnel *vt, const char *name)
  190. {
  191. struct network *net = vt->net;
  192. struct network_group *group;
  193. int i;
  194. group = avl_find_element(&net->groups, name, group, node);
  195. if (!group)
  196. return;
  197. for (i = 0; i < group->n_members; i++)
  198. __vxlan_mark_forward_host(vt, group->members[i]);
  199. }
  200. static void
  201. vxlan_init_forward_ports(struct vxlan_tunnel *vt, struct blob_attr *data)
  202. {
  203. unsigned int len = bitmask_size(vt->s->n_members);
  204. struct blob_attr *cur;
  205. int rem;
  206. vt->cur_forward_ports = realloc(vt->cur_forward_ports, len);
  207. memset(vt->cur_forward_ports, 0, len);
  208. if (!data || blobmsg_check_array(data, BLOBMSG_TYPE_STRING) <= 0) {
  209. free(vt->forward_ports);
  210. vt->forward_ports = NULL;
  211. return;
  212. }
  213. vt->forward_ports = realloc(vt->forward_ports, len);
  214. memset(vt->forward_ports, 0, len);
  215. blobmsg_for_each_attr(cur, data, rem) {
  216. const char *name = blobmsg_get_string(cur);
  217. if (name[0] == '@')
  218. vxlan_mark_forward_group(vt, name + 1);
  219. else
  220. vxlan_mark_forward_host(vt, name);
  221. }
  222. }
  223. static bool
  224. vxlan_config_equal(struct network_service *s1, struct network_service *s2)
  225. {
  226. int i;
  227. if (!blob_attr_equal(s1->config, s2->config))
  228. return false;
  229. if (s1->n_members != s2->n_members)
  230. return false;
  231. for (i = 0; i < s1->n_members; i++)
  232. if (memcmp(s1->members[i]->peer.key, s2->members[i]->peer.key,
  233. CURVE25519_KEY_SIZE) != 0)
  234. return false;
  235. return true;
  236. }
  237. static void
  238. vxlan_init(struct network *net, struct network_service *s,
  239. struct network_service *s_old)
  240. {
  241. enum {
  242. VXCFG_ATTR_FWD_PORTS,
  243. VXCFG_ATTR_ID,
  244. VXCFG_ATTR_PORT,
  245. VXCFG_ATTR_MTU,
  246. __VXCFG_ATTR_MAX
  247. };
  248. static const struct blobmsg_policy policy[__VXCFG_ATTR_MAX] = {
  249. [VXCFG_ATTR_FWD_PORTS] = { "forward_ports", BLOBMSG_TYPE_ARRAY },
  250. [VXCFG_ATTR_ID] = { "id", BLOBMSG_TYPE_INT32 },
  251. [VXCFG_ATTR_PORT] = { "port", BLOBMSG_TYPE_INT32 },
  252. [VXCFG_ATTR_MTU] = { "mtu", BLOBMSG_TYPE_INT32 },
  253. };
  254. struct blob_attr *tb[__VXCFG_ATTR_MAX] = {};
  255. struct blob_attr *cur;
  256. struct vxlan_tunnel *vt = s->vxlan;
  257. const char *name;
  258. if (s_old) {
  259. vt = s_old->vxlan;
  260. s_old->vxlan = NULL;
  261. if (!vt)
  262. return;
  263. if (vxlan_config_equal(s, s_old)) {
  264. s->vxlan = vt;
  265. vt->s = s;
  266. return;
  267. }
  268. vxlan_tunnel_teardown(vt);
  269. goto init;
  270. }
  271. name = vxlan_find_ifname(net, network_service_name(s));
  272. if (!name) {
  273. D_SERVICE(net, s, "no configured tunnel ifname");
  274. return;
  275. }
  276. vt = calloc(1, sizeof(*s->vxlan));
  277. snprintf(vt->ifname, sizeof(vt->ifname), "%s", name);
  278. vt->net = net;
  279. init:
  280. s->vxlan = vt;
  281. vt->s = s;
  282. if (s->config)
  283. blobmsg_parse(policy, __VXCFG_ATTR_MAX, tb, blobmsg_data(s->config),
  284. blobmsg_len(s->config));
  285. vxlan_init_forward_ports(vt, tb[VXCFG_ATTR_FWD_PORTS]);
  286. if ((cur = tb[VXCFG_ATTR_ID]) != NULL)
  287. vt->vni = blobmsg_get_u32(cur) & 0x00ffffff;
  288. else
  289. vt->vni = ~0;
  290. if ((cur = tb[VXCFG_ATTR_PORT]) != NULL)
  291. vt->port = blobmsg_get_u32(cur);
  292. else
  293. vt->port = 4789;
  294. if ((cur = tb[VXCFG_ATTR_MTU]) != NULL)
  295. vt->mtu = blobmsg_get_u32(cur);
  296. else
  297. vt->mtu = 1500;
  298. vxlan_tunnel_init(vt);
  299. }
  300. static void
  301. vxlan_free(struct network *net, struct network_service *s)
  302. {
  303. struct vxlan_tunnel *vt = s->vxlan;
  304. if (!vt)
  305. return;
  306. vxlan_tunnel_teardown(vt);
  307. s->vxlan = NULL;
  308. free(vt->forward_ports);
  309. free(vt);
  310. }
  311. const struct service_ops vxlan_ops = {
  312. .init = vxlan_init,
  313. .free = vxlan_free,
  314. .peer_update = vxlan_peer_update,
  315. };