ip_vs_proto.c 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398
  1. /*
  2. * ip_vs_proto.c: transport protocol load balancing support for IPVS
  3. *
  4. * Authors: Wensong Zhang <wensong@linuxvirtualserver.org>
  5. * Julian Anastasov <ja@ssi.bg>
  6. *
  7. * This program is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU General Public License
  9. * as published by the Free Software Foundation; either version
  10. * 2 of the License, or (at your option) any later version.
  11. *
  12. * Changes:
  13. *
  14. */
  15. #define KMSG_COMPONENT "IPVS"
  16. #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
  17. #include <linux/module.h>
  18. #include <linux/kernel.h>
  19. #include <linux/skbuff.h>
  20. #include <linux/gfp.h>
  21. #include <linux/in.h>
  22. #include <linux/ip.h>
  23. #include <net/protocol.h>
  24. #include <net/tcp.h>
  25. #include <net/udp.h>
  26. #include <linux/stat.h>
  27. #include <linux/proc_fs.h>
  28. #include <net/ip_vs.h>
  29. /*
  30. * IPVS protocols can only be registered/unregistered when the ipvs
  31. * module is loaded/unloaded, so no lock is needed in accessing the
  32. * ipvs protocol table.
  33. */
  34. #define IP_VS_PROTO_TAB_SIZE 32 /* must be power of 2 */
  35. #define IP_VS_PROTO_HASH(proto) ((proto) & (IP_VS_PROTO_TAB_SIZE-1))
  36. static struct ip_vs_protocol *ip_vs_proto_table[IP_VS_PROTO_TAB_SIZE];
  37. /*
  38. * register an ipvs protocol
  39. */
  40. static int __used __init register_ip_vs_protocol(struct ip_vs_protocol *pp)
  41. {
  42. unsigned int hash = IP_VS_PROTO_HASH(pp->protocol);
  43. pp->next = ip_vs_proto_table[hash];
  44. ip_vs_proto_table[hash] = pp;
  45. if (pp->init != NULL)
  46. pp->init(pp);
  47. return 0;
  48. }
  49. /*
  50. * register an ipvs protocols netns related data
  51. */
  52. static int
  53. register_ip_vs_proto_netns(struct netns_ipvs *ipvs, struct ip_vs_protocol *pp)
  54. {
  55. unsigned int hash = IP_VS_PROTO_HASH(pp->protocol);
  56. struct ip_vs_proto_data *pd =
  57. kzalloc(sizeof(struct ip_vs_proto_data), GFP_KERNEL);
  58. if (!pd)
  59. return -ENOMEM;
  60. pd->pp = pp; /* For speed issues */
  61. pd->next = ipvs->proto_data_table[hash];
  62. ipvs->proto_data_table[hash] = pd;
  63. atomic_set(&pd->appcnt, 0); /* Init app counter */
  64. if (pp->init_netns != NULL) {
  65. int ret = pp->init_netns(ipvs, pd);
  66. if (ret) {
  67. /* unlink an free proto data */
  68. ipvs->proto_data_table[hash] = pd->next;
  69. kfree(pd);
  70. return ret;
  71. }
  72. }
  73. return 0;
  74. }
  75. /*
  76. * unregister an ipvs protocol
  77. */
  78. static int unregister_ip_vs_protocol(struct ip_vs_protocol *pp)
  79. {
  80. struct ip_vs_protocol **pp_p;
  81. unsigned int hash = IP_VS_PROTO_HASH(pp->protocol);
  82. pp_p = &ip_vs_proto_table[hash];
  83. for (; *pp_p; pp_p = &(*pp_p)->next) {
  84. if (*pp_p == pp) {
  85. *pp_p = pp->next;
  86. if (pp->exit != NULL)
  87. pp->exit(pp);
  88. return 0;
  89. }
  90. }
  91. return -ESRCH;
  92. }
  93. /*
  94. * unregister an ipvs protocols netns data
  95. */
  96. static int
  97. unregister_ip_vs_proto_netns(struct netns_ipvs *ipvs, struct ip_vs_proto_data *pd)
  98. {
  99. struct ip_vs_proto_data **pd_p;
  100. unsigned int hash = IP_VS_PROTO_HASH(pd->pp->protocol);
  101. pd_p = &ipvs->proto_data_table[hash];
  102. for (; *pd_p; pd_p = &(*pd_p)->next) {
  103. if (*pd_p == pd) {
  104. *pd_p = pd->next;
  105. if (pd->pp->exit_netns != NULL)
  106. pd->pp->exit_netns(ipvs, pd);
  107. kfree(pd);
  108. return 0;
  109. }
  110. }
  111. return -ESRCH;
  112. }
  113. /*
  114. * get ip_vs_protocol object by its proto.
  115. */
  116. struct ip_vs_protocol * ip_vs_proto_get(unsigned short proto)
  117. {
  118. struct ip_vs_protocol *pp;
  119. unsigned int hash = IP_VS_PROTO_HASH(proto);
  120. for (pp = ip_vs_proto_table[hash]; pp; pp = pp->next) {
  121. if (pp->protocol == proto)
  122. return pp;
  123. }
  124. return NULL;
  125. }
  126. EXPORT_SYMBOL(ip_vs_proto_get);
  127. /*
  128. * get ip_vs_protocol object data by netns and proto
  129. */
  130. struct ip_vs_proto_data *
  131. ip_vs_proto_data_get(struct netns_ipvs *ipvs, unsigned short proto)
  132. {
  133. struct ip_vs_proto_data *pd;
  134. unsigned int hash = IP_VS_PROTO_HASH(proto);
  135. for (pd = ipvs->proto_data_table[hash]; pd; pd = pd->next) {
  136. if (pd->pp->protocol == proto)
  137. return pd;
  138. }
  139. return NULL;
  140. }
  141. EXPORT_SYMBOL(ip_vs_proto_data_get);
  142. /*
  143. * Propagate event for state change to all protocols
  144. */
  145. void ip_vs_protocol_timeout_change(struct netns_ipvs *ipvs, int flags)
  146. {
  147. struct ip_vs_proto_data *pd;
  148. int i;
  149. for (i = 0; i < IP_VS_PROTO_TAB_SIZE; i++) {
  150. for (pd = ipvs->proto_data_table[i]; pd; pd = pd->next) {
  151. if (pd->pp->timeout_change)
  152. pd->pp->timeout_change(pd, flags);
  153. }
  154. }
  155. }
  156. int *
  157. ip_vs_create_timeout_table(int *table, int size)
  158. {
  159. return kmemdup(table, size, GFP_KERNEL);
  160. }
  161. /*
  162. * Set timeout value for state specified by name
  163. */
  164. int
  165. ip_vs_set_state_timeout(int *table, int num, const char *const *names,
  166. const char *name, int to)
  167. {
  168. int i;
  169. if (!table || !name || !to)
  170. return -EINVAL;
  171. for (i = 0; i < num; i++) {
  172. if (strcmp(names[i], name))
  173. continue;
  174. table[i] = to * HZ;
  175. return 0;
  176. }
  177. return -ENOENT;
  178. }
  179. const char * ip_vs_state_name(__u16 proto, int state)
  180. {
  181. struct ip_vs_protocol *pp = ip_vs_proto_get(proto);
  182. if (pp == NULL || pp->state_name == NULL)
  183. return (IPPROTO_IP == proto) ? "NONE" : "ERR!";
  184. return pp->state_name(state);
  185. }
  186. static void
  187. ip_vs_tcpudp_debug_packet_v4(struct ip_vs_protocol *pp,
  188. const struct sk_buff *skb,
  189. int offset,
  190. const char *msg)
  191. {
  192. char buf[128];
  193. struct iphdr _iph, *ih;
  194. ih = skb_header_pointer(skb, offset, sizeof(_iph), &_iph);
  195. if (ih == NULL)
  196. sprintf(buf, "TRUNCATED");
  197. else if (ih->frag_off & htons(IP_OFFSET))
  198. sprintf(buf, "%pI4->%pI4 frag", &ih->saddr, &ih->daddr);
  199. else {
  200. __be16 _ports[2], *pptr;
  201. pptr = skb_header_pointer(skb, offset + ih->ihl*4,
  202. sizeof(_ports), _ports);
  203. if (pptr == NULL)
  204. sprintf(buf, "TRUNCATED %pI4->%pI4",
  205. &ih->saddr, &ih->daddr);
  206. else
  207. sprintf(buf, "%pI4:%u->%pI4:%u",
  208. &ih->saddr, ntohs(pptr[0]),
  209. &ih->daddr, ntohs(pptr[1]));
  210. }
  211. pr_debug("%s: %s %s\n", msg, pp->name, buf);
  212. }
  213. #ifdef CONFIG_IP_VS_IPV6
  214. static void
  215. ip_vs_tcpudp_debug_packet_v6(struct ip_vs_protocol *pp,
  216. const struct sk_buff *skb,
  217. int offset,
  218. const char *msg)
  219. {
  220. char buf[192];
  221. struct ipv6hdr _iph, *ih;
  222. ih = skb_header_pointer(skb, offset, sizeof(_iph), &_iph);
  223. if (ih == NULL)
  224. sprintf(buf, "TRUNCATED");
  225. else if (ih->nexthdr == IPPROTO_FRAGMENT)
  226. sprintf(buf, "%pI6c->%pI6c frag", &ih->saddr, &ih->daddr);
  227. else {
  228. __be16 _ports[2], *pptr;
  229. pptr = skb_header_pointer(skb, offset + sizeof(struct ipv6hdr),
  230. sizeof(_ports), _ports);
  231. if (pptr == NULL)
  232. sprintf(buf, "TRUNCATED %pI6c->%pI6c",
  233. &ih->saddr, &ih->daddr);
  234. else
  235. sprintf(buf, "%pI6c:%u->%pI6c:%u",
  236. &ih->saddr, ntohs(pptr[0]),
  237. &ih->daddr, ntohs(pptr[1]));
  238. }
  239. pr_debug("%s: %s %s\n", msg, pp->name, buf);
  240. }
  241. #endif
  242. void
  243. ip_vs_tcpudp_debug_packet(int af, struct ip_vs_protocol *pp,
  244. const struct sk_buff *skb,
  245. int offset,
  246. const char *msg)
  247. {
  248. #ifdef CONFIG_IP_VS_IPV6
  249. if (af == AF_INET6)
  250. ip_vs_tcpudp_debug_packet_v6(pp, skb, offset, msg);
  251. else
  252. #endif
  253. ip_vs_tcpudp_debug_packet_v4(pp, skb, offset, msg);
  254. }
  255. /*
  256. * per network name-space init
  257. */
  258. int __net_init ip_vs_protocol_net_init(struct netns_ipvs *ipvs)
  259. {
  260. int i, ret;
  261. static struct ip_vs_protocol *protos[] = {
  262. #ifdef CONFIG_IP_VS_PROTO_TCP
  263. &ip_vs_protocol_tcp,
  264. #endif
  265. #ifdef CONFIG_IP_VS_PROTO_UDP
  266. &ip_vs_protocol_udp,
  267. #endif
  268. #ifdef CONFIG_IP_VS_PROTO_SCTP
  269. &ip_vs_protocol_sctp,
  270. #endif
  271. #ifdef CONFIG_IP_VS_PROTO_AH
  272. &ip_vs_protocol_ah,
  273. #endif
  274. #ifdef CONFIG_IP_VS_PROTO_ESP
  275. &ip_vs_protocol_esp,
  276. #endif
  277. };
  278. for (i = 0; i < ARRAY_SIZE(protos); i++) {
  279. ret = register_ip_vs_proto_netns(ipvs, protos[i]);
  280. if (ret < 0)
  281. goto cleanup;
  282. }
  283. return 0;
  284. cleanup:
  285. ip_vs_protocol_net_cleanup(ipvs);
  286. return ret;
  287. }
  288. void __net_exit ip_vs_protocol_net_cleanup(struct netns_ipvs *ipvs)
  289. {
  290. struct ip_vs_proto_data *pd;
  291. int i;
  292. /* unregister all the ipvs proto data for this netns */
  293. for (i = 0; i < IP_VS_PROTO_TAB_SIZE; i++) {
  294. while ((pd = ipvs->proto_data_table[i]) != NULL)
  295. unregister_ip_vs_proto_netns(ipvs, pd);
  296. }
  297. }
  298. int __init ip_vs_protocol_init(void)
  299. {
  300. char protocols[64];
  301. #define REGISTER_PROTOCOL(p) \
  302. do { \
  303. register_ip_vs_protocol(p); \
  304. strcat(protocols, ", "); \
  305. strcat(protocols, (p)->name); \
  306. } while (0)
  307. protocols[0] = '\0';
  308. protocols[2] = '\0';
  309. #ifdef CONFIG_IP_VS_PROTO_TCP
  310. REGISTER_PROTOCOL(&ip_vs_protocol_tcp);
  311. #endif
  312. #ifdef CONFIG_IP_VS_PROTO_UDP
  313. REGISTER_PROTOCOL(&ip_vs_protocol_udp);
  314. #endif
  315. #ifdef CONFIG_IP_VS_PROTO_SCTP
  316. REGISTER_PROTOCOL(&ip_vs_protocol_sctp);
  317. #endif
  318. #ifdef CONFIG_IP_VS_PROTO_AH
  319. REGISTER_PROTOCOL(&ip_vs_protocol_ah);
  320. #endif
  321. #ifdef CONFIG_IP_VS_PROTO_ESP
  322. REGISTER_PROTOCOL(&ip_vs_protocol_esp);
  323. #endif
  324. pr_info("Registered protocols (%s)\n", &protocols[2]);
  325. return 0;
  326. }
  327. void ip_vs_protocol_cleanup(void)
  328. {
  329. struct ip_vs_protocol *pp;
  330. int i;
  331. /* unregister all the ipvs protocols */
  332. for (i = 0; i < IP_VS_PROTO_TAB_SIZE; i++) {
  333. while ((pp = ip_vs_proto_table[i]) != NULL)
  334. unregister_ip_vs_protocol(pp);
  335. }
  336. }