diff -r 14cbeb78966a -r 93dcf1920c71 components/dnsmasq/patches/05_dhcp_bind_fix.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/components/dnsmasq/patches/05_dhcp_bind_fix.patch Mon Sep 26 16:23:01 2016 -0700 @@ -0,0 +1,139 @@ +Patch to address a scalability issue when using dnsmasq in Openstack, +that causes DHCP to be extremely slow. + +This patch was developed in-house. Since it is Solaris-specific, it is not +suitable for upstream. + +--- dnsmasq-2.75/src/dhcp-common.c 2015-07-30 12:59:07.000000000 -0700 ++++ new/src/dhcp-common.c 2016-09-22 15:12:02.104708123 -0700 +@@ -493,6 +493,58 @@ + errno != EPERM) + die(_("failed to set SO_BINDTODEVICE on DHCP socket: %s"), NULL, EC_BADNET); + } ++#elif defined(HAVE_SOLARIS_NETWORK) ++int which_ifindex(void) ++{ ++ /* If we are doing DHCP on exactly one interface, and using Solaris, we want ++ * to limit packet transmission/reception to that interface using IP_BOUND_IF ++ * for IPv4 and IPV6_BOUND_IF for IPv6. This is for the use case of OpenStack, ++ * which runs a new dnsmasq instance for each network it creates. Without this ++ * socket option, each of the dnsmasq process would unnecessarily process ++ * packets that arrive on other interfaces as well, thus slowing down the ++ * entire DHCP process. ++ */ ++ ++ struct irec *iface, *found; ++ struct iname *if_tmp; ++ ++ if (!daemon->if_names) ++ return -1; ++ ++ for (if_tmp = daemon->if_names; if_tmp; if_tmp = if_tmp->next) ++ if (if_tmp->name && (!if_tmp->used || strchr(if_tmp->name, '*'))) ++ return -1; ++ ++ for (found = NULL, iface = daemon->interfaces; iface; iface = iface->next) ++ if (iface->dhcp_ok) ++ { ++ if (!found) ++ found = iface; ++ else if (strcmp(found->name, iface->name) != 0) ++ return -1; /* more than one. */ ++ } ++ ++ if (found) ++ return found->index; ++ ++ return -1; ++} ++ ++void bindtoif(int ifindex, int fd, int is_dhcp6) ++{ ++ if (is_dhcp6) ++ { ++ if (setsockopt(fd, IPPROTO_IPV6, IPV6_BOUND_IF, (char *)&ifindex, sizeof(ifindex)) == -1 && ++ errno != EPERM) ++ die(_("failed to set IPv6_BOUND_IF on DHCP socket: %s"), NULL, EC_BADNET); ++ } ++ else ++ { ++ if (setsockopt(fd, IPPROTO_IP, IP_BOUND_IF, &ifindex, sizeof(ifindex)) == -1 && ++ errno != EPERM) ++ die(_("failed to set IP_BOUND_IF on DHCP socket: %s"), NULL, EC_BADNET); ++ } ++} + #endif + + static const struct opttab_t { +--- dnsmasq-2.75/src/dnsmasq.h 2016-09-22 15:20:19.502011580 -0700 ++++ new/src/dnsmasq.h 2016-09-22 13:17:03.865473011 -0700 +@@ -1464,6 +1464,9 @@ + #ifdef HAVE_LINUX_NETWORK + char *whichdevice(void); + void bindtodevice(char *device, int fd); ++#elif defined(HAVE_SOLARIS_NETWORK) ++int which_ifindex(void); ++void bindtoif(int ifindex, int fd, int is_dhcp6); + #endif + # ifdef HAVE_DHCP6 + void display_opts6(void); +--- dnsmasq-2.75/src/dnsmasq.c 2015-07-30 12:59:07.000000000 -0700 ++++ new/src/dnsmasq.c 2016-09-22 15:20:03.040122945 -0700 +@@ -54,6 +54,10 @@ + char *bound_device = NULL; + int did_bind = 0; + #endif ++#if defined(HAVE_SOLARIS_NETWORK) ++ int bound_ifindex = -1; ++ int did_bind = 0; ++#endif + #if defined(HAVE_DHCP) || defined(HAVE_DHCP6) + struct dhcp_context *context; + struct dhcp_relay *relay; +@@ -306,6 +310,23 @@ + did_bind = 1; + } + } ++#elif defined(HAVE_SOLARIS_NETWORK) && defined(HAVE_DHCP) ++ bound_ifindex = which_ifindex(); ++ ++ if (daemon->dhcp) ++ { ++ if (!daemon->relay4 && bound_ifindex >= 0) ++ { ++ bindtoif(bound_ifindex, daemon->dhcpfd, 0); ++ did_bind = 1; ++ } ++ ++ if (daemon->enable_pxe && bound_ifindex >= 0) ++ { ++ bindtoif(bound_ifindex, daemon->pxefd, 0); ++ did_bind = 1; ++ } ++ } + #endif + + #if defined(HAVE_LINUX_NETWORK) && defined(HAVE_DHCP6) +@@ -314,6 +335,12 @@ + bindtodevice(bound_device, daemon->dhcp6fd); + did_bind = 1; + } ++#elif defined(HAVE_SOLARIS_NETWORK) && defined(HAVE_DHCP6) ++ if (daemon->doing_dhcp6 && !daemon->relay6 && bound_ifindex >= 0) ++ { ++ bindtoif(bound_ifindex, daemon->dhcp6fd, 1); ++ did_bind = 1; ++ } + #endif + } + else +@@ -788,6 +815,9 @@ + # ifdef HAVE_LINUX_NETWORK + if (did_bind) + my_syslog(MS_DHCP | LOG_INFO, _("DHCP, sockets bound exclusively to interface %s"), bound_device); ++# elif defined(HAVE_SOLARIS_NETWORK) ++ if (did_bind) ++ my_syslog(MS_DHCP | LOG_INFO, _("DHCP, sockets bound exclusively to interface index %d"), bound_ifindex); + # endif + + /* after dhcp_contruct_contexts */