components/dnsmasq/patches/05_dhcp_bind_fix.patch
changeset 6979 93dcf1920c71
equal deleted inserted replaced
6978:14cbeb78966a 6979:93dcf1920c71
       
     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 */