|
1 Patch to address a scalability issue when using dnsmasq in Openstack, |
|
2 that causes DHCP to be extremely slow. |
|
3 |
|
4 This patch was developed in-house. Since it is Solaris-specific, it is not |
|
5 suitable for upstream. |
|
6 |
|
7 --- dnsmasq-2.75/src/dhcp-common.c 2015-07-30 12:59:07.000000000 -0700 |
|
8 +++ new/src/dhcp-common.c 2016-09-22 15:12:02.104708123 -0700 |
|
9 @@ -493,6 +493,58 @@ |
|
10 errno != EPERM) |
|
11 die(_("failed to set SO_BINDTODEVICE on DHCP socket: %s"), NULL, EC_BADNET); |
|
12 } |
|
13 +#elif defined(HAVE_SOLARIS_NETWORK) |
|
14 +int which_ifindex(void) |
|
15 +{ |
|
16 + /* If we are doing DHCP on exactly one interface, and using Solaris, we want |
|
17 + * to limit packet transmission/reception to that interface using IP_BOUND_IF |
|
18 + * for IPv4 and IPV6_BOUND_IF for IPv6. This is for the use case of OpenStack, |
|
19 + * which runs a new dnsmasq instance for each network it creates. Without this |
|
20 + * socket option, each of the dnsmasq process would unnecessarily process |
|
21 + * packets that arrive on other interfaces as well, thus slowing down the |
|
22 + * entire DHCP process. |
|
23 + */ |
|
24 + |
|
25 + struct irec *iface, *found; |
|
26 + struct iname *if_tmp; |
|
27 + |
|
28 + if (!daemon->if_names) |
|
29 + return -1; |
|
30 + |
|
31 + for (if_tmp = daemon->if_names; if_tmp; if_tmp = if_tmp->next) |
|
32 + if (if_tmp->name && (!if_tmp->used || strchr(if_tmp->name, '*'))) |
|
33 + return -1; |
|
34 + |
|
35 + for (found = NULL, iface = daemon->interfaces; iface; iface = iface->next) |
|
36 + if (iface->dhcp_ok) |
|
37 + { |
|
38 + if (!found) |
|
39 + found = iface; |
|
40 + else if (strcmp(found->name, iface->name) != 0) |
|
41 + return -1; /* more than one. */ |
|
42 + } |
|
43 + |
|
44 + if (found) |
|
45 + return found->index; |
|
46 + |
|
47 + return -1; |
|
48 +} |
|
49 + |
|
50 +void bindtoif(int ifindex, int fd, int is_dhcp6) |
|
51 +{ |
|
52 + if (is_dhcp6) |
|
53 + { |
|
54 + if (setsockopt(fd, IPPROTO_IPV6, IPV6_BOUND_IF, (char *)&ifindex, sizeof(ifindex)) == -1 && |
|
55 + errno != EPERM) |
|
56 + die(_("failed to set IPv6_BOUND_IF on DHCP socket: %s"), NULL, EC_BADNET); |
|
57 + } |
|
58 + else |
|
59 + { |
|
60 + if (setsockopt(fd, IPPROTO_IP, IP_BOUND_IF, &ifindex, sizeof(ifindex)) == -1 && |
|
61 + errno != EPERM) |
|
62 + die(_("failed to set IP_BOUND_IF on DHCP socket: %s"), NULL, EC_BADNET); |
|
63 + } |
|
64 +} |
|
65 #endif |
|
66 |
|
67 static const struct opttab_t { |
|
68 --- dnsmasq-2.75/src/dnsmasq.h 2016-09-22 15:20:19.502011580 -0700 |
|
69 +++ new/src/dnsmasq.h 2016-09-22 13:17:03.865473011 -0700 |
|
70 @@ -1464,6 +1464,9 @@ |
|
71 #ifdef HAVE_LINUX_NETWORK |
|
72 char *whichdevice(void); |
|
73 void bindtodevice(char *device, int fd); |
|
74 +#elif defined(HAVE_SOLARIS_NETWORK) |
|
75 +int which_ifindex(void); |
|
76 +void bindtoif(int ifindex, int fd, int is_dhcp6); |
|
77 #endif |
|
78 # ifdef HAVE_DHCP6 |
|
79 void display_opts6(void); |
|
80 --- dnsmasq-2.75/src/dnsmasq.c 2015-07-30 12:59:07.000000000 -0700 |
|
81 +++ new/src/dnsmasq.c 2016-09-22 15:20:03.040122945 -0700 |
|
82 @@ -54,6 +54,10 @@ |
|
83 char *bound_device = NULL; |
|
84 int did_bind = 0; |
|
85 #endif |
|
86 +#if defined(HAVE_SOLARIS_NETWORK) |
|
87 + int bound_ifindex = -1; |
|
88 + int did_bind = 0; |
|
89 +#endif |
|
90 #if defined(HAVE_DHCP) || defined(HAVE_DHCP6) |
|
91 struct dhcp_context *context; |
|
92 struct dhcp_relay *relay; |
|
93 @@ -306,6 +310,23 @@ |
|
94 did_bind = 1; |
|
95 } |
|
96 } |
|
97 +#elif defined(HAVE_SOLARIS_NETWORK) && defined(HAVE_DHCP) |
|
98 + bound_ifindex = which_ifindex(); |
|
99 + |
|
100 + if (daemon->dhcp) |
|
101 + { |
|
102 + if (!daemon->relay4 && bound_ifindex >= 0) |
|
103 + { |
|
104 + bindtoif(bound_ifindex, daemon->dhcpfd, 0); |
|
105 + did_bind = 1; |
|
106 + } |
|
107 + |
|
108 + if (daemon->enable_pxe && bound_ifindex >= 0) |
|
109 + { |
|
110 + bindtoif(bound_ifindex, daemon->pxefd, 0); |
|
111 + did_bind = 1; |
|
112 + } |
|
113 + } |
|
114 #endif |
|
115 |
|
116 #if defined(HAVE_LINUX_NETWORK) && defined(HAVE_DHCP6) |
|
117 @@ -314,6 +335,12 @@ |
|
118 bindtodevice(bound_device, daemon->dhcp6fd); |
|
119 did_bind = 1; |
|
120 } |
|
121 +#elif defined(HAVE_SOLARIS_NETWORK) && defined(HAVE_DHCP6) |
|
122 + if (daemon->doing_dhcp6 && !daemon->relay6 && bound_ifindex >= 0) |
|
123 + { |
|
124 + bindtoif(bound_ifindex, daemon->dhcp6fd, 1); |
|
125 + did_bind = 1; |
|
126 + } |
|
127 #endif |
|
128 } |
|
129 else |
|
130 @@ -788,6 +815,9 @@ |
|
131 # ifdef HAVE_LINUX_NETWORK |
|
132 if (did_bind) |
|
133 my_syslog(MS_DHCP | LOG_INFO, _("DHCP, sockets bound exclusively to interface %s"), bound_device); |
|
134 +# elif defined(HAVE_SOLARIS_NETWORK) |
|
135 + if (did_bind) |
|
136 + my_syslog(MS_DHCP | LOG_INFO, _("DHCP, sockets bound exclusively to interface index %d"), bound_ifindex); |
|
137 # endif |
|
138 |
|
139 /* after dhcp_contruct_contexts */ |