diff options
author | Markus Friedl <markus@cvs.openbsd.org> | 2007-09-18 18:56:03 +0000 |
---|---|---|
committer | Markus Friedl <markus@cvs.openbsd.org> | 2007-09-18 18:56:03 +0000 |
commit | d8c8aedc05fb2cb0525780a91a06a0470ead8d28 (patch) | |
tree | 8ad63d183073defcec00688b5f81884f308a2174 /sys | |
parent | 73ab101f302f601f84bacdb4b550ba93e28812c1 (diff) |
allow 4095 instead of 20 multicast group memberships per socket (you need
one entry for each multicast group and interface combination). this allows
you to run OSPF with more than 10 interfaces.
adapted from freebsd; ok claudio, henning, mpf
Diffstat (limited to 'sys')
-rw-r--r-- | sys/net/if_pfsync.c | 7 | ||||
-rw-r--r-- | sys/netinet/in.h | 10 | ||||
-rw-r--r-- | sys/netinet/ip_carp.c | 13 | ||||
-rw-r--r-- | sys/netinet/ip_output.c | 46 | ||||
-rw-r--r-- | sys/netinet/ip_var.h | 5 |
5 files changed, 66 insertions, 15 deletions
diff --git a/sys/net/if_pfsync.c b/sys/net/if_pfsync.c index 6edc36e3512..839d7bbfa1f 100644 --- a/sys/net/if_pfsync.c +++ b/sys/net/if_pfsync.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_pfsync.c,v 1.86 2007/09/15 16:43:51 henning Exp $ */ +/* $OpenBSD: if_pfsync.c,v 1.87 2007/09/18 18:56:02 markus Exp $ */ /* * Copyright (c) 2002 Michael Shalayeff @@ -141,6 +141,10 @@ pfsync_clone_create(struct if_clone *ifc, int unit) pfsyncif->sc_ureq_sent = 0; pfsyncif->sc_bulk_send_next = NULL; pfsyncif->sc_bulk_terminator = NULL; + pfsyncif->sc_imo.imo_membership = (struct in_multi **)malloc( + (sizeof(struct in_multi *) * IP_MIN_MEMBERSHIPS), M_IPMOPTS, + M_WAITOK|M_ZERO); + pfsyncif->sc_imo.imo_max_memberships = IP_MIN_MEMBERSHIPS; ifp = &pfsyncif->sc_if; snprintf(ifp->if_xname, sizeof ifp->if_xname, "pfsync%d", unit); ifp->if_softc = pfsyncif; @@ -176,6 +180,7 @@ pfsync_clone_destroy(struct ifnet *ifp) bpfdetach(ifp); #endif if_detach(ifp); + free(pfsyncif->sc_imo.imo_membership, M_IPMOPTS); free(pfsyncif, M_DEVBUF); pfsyncif = NULL; return (0); diff --git a/sys/netinet/in.h b/sys/netinet/in.h index bbbd2f42888..5cfdf0e66c2 100644 --- a/sys/netinet/in.h +++ b/sys/netinet/in.h @@ -1,4 +1,4 @@ -/* $OpenBSD: in.h,v 1.73 2006/10/11 09:34:51 henning Exp $ */ +/* $OpenBSD: in.h,v 1.74 2007/09/18 18:56:02 markus Exp $ */ /* $NetBSD: in.h,v 1.20 1996/02/13 23:41:47 christos Exp $ */ /* @@ -290,7 +290,13 @@ struct ip_opts { */ #define IP_DEFAULT_MULTICAST_TTL 1 /* normally limit m'casts to 1 hop */ #define IP_DEFAULT_MULTICAST_LOOP 1 /* normally hear sends if a member */ -#define IP_MAX_MEMBERSHIPS 20 /* per socket; must fit in one mbuf */ +/* + * The imo_membership vector for each socket starts at IP_MIN_MEMBERSHIPS + * and is dynamically allocated at run-time, bounded by IP_MAX_MEMBERSHIPS, + * and is reallocated when needed, sized according to a power-of-two increment. + */ +#define IP_MIN_MEMBERSHIPS 15 +#define IP_MAX_MEMBERSHIPS 4095 /* * Argument structure for IP_ADD_MEMBERSHIP and IP_DROP_MEMBERSHIP. diff --git a/sys/netinet/ip_carp.c b/sys/netinet/ip_carp.c index 5f47ccfc8b1..b5272dd3083 100644 --- a/sys/netinet/ip_carp.c +++ b/sys/netinet/ip_carp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_carp.c,v 1.149 2007/09/18 09:18:04 mpf Exp $ */ +/* $OpenBSD: ip_carp.c,v 1.150 2007/09/18 18:56:02 markus Exp $ */ /* * Copyright (c) 2002 Michael Shalayeff. All rights reserved. @@ -846,6 +846,10 @@ carp_clone_create(ifc, unit) #ifdef INET6 sc->sc_im6o.im6o_multicast_hlim = CARP_DFLTTL; #endif /* INET6 */ + sc->sc_imo.imo_membership = (struct in_multi **)malloc( + (sizeof(struct in_multi *) * IP_MIN_MEMBERSHIPS), M_IPMOPTS, + M_WAITOK|M_ZERO); + sc->sc_imo.imo_max_memberships = IP_MIN_MEMBERSHIPS; timeout_set(&sc->sc_ad_tmo, carp_send_ad, sc); timeout_set(&sc->sc_md_tmo, carp_master_down, sc); @@ -879,10 +883,13 @@ carp_clone_create(ifc, unit) int carp_clone_destroy(struct ifnet *ifp) { - carpdetach(ifp->if_softc); + struct carp_softc *sc = ifp->if_softc; + + carpdetach(sc); ether_ifdetach(ifp); if_detach(ifp); - free(ifp->if_softc, M_DEVBUF); + free(sc->sc_imo.imo_membership, M_IPMOPTS); + free(sc, M_DEVBUF); return (0); } diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c index e4c01b26373..73490dcc154 100644 --- a/sys/netinet/ip_output.c +++ b/sys/netinet/ip_output.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_output.c,v 1.188 2007/07/20 19:00:35 claudio Exp $ */ +/* $OpenBSD: ip_output.c,v 1.189 2007/09/18 18:56:02 markus Exp $ */ /* $NetBSD: ip_output.c,v 1.28 1996/02/13 23:43:07 christos Exp $ */ /* @@ -1703,6 +1703,7 @@ ip_setmoptions(optname, imop, m) struct ip_mreq *mreq; struct ifnet *ifp; struct ip_moptions *imo = *imop; + struct in_multi **immp; struct route ro; struct sockaddr_in *dst; @@ -1712,13 +1713,17 @@ ip_setmoptions(optname, imop, m) * allocate one and initialize to default values. */ imo = (struct ip_moptions *)malloc(sizeof(*imo), M_IPMOPTS, - M_WAITOK); - + M_WAITOK|M_ZERO); + immp = (struct in_multi **)malloc( + (sizeof(*immp) * IP_MIN_MEMBERSHIPS), M_IPMOPTS, + M_WAITOK|M_ZERO); *imop = imo; imo->imo_multicast_ifp = NULL; imo->imo_multicast_ttl = IP_DEFAULT_MULTICAST_TTL; imo->imo_multicast_loop = IP_DEFAULT_MULTICAST_LOOP; imo->imo_num_memberships = 0; + imo->imo_max_memberships = IP_MIN_MEMBERSHIPS; + imo->imo_membership = immp; } switch (optname) { @@ -1834,9 +1839,34 @@ ip_setmoptions(optname, imop, m) error = EADDRINUSE; break; } - if (i == IP_MAX_MEMBERSHIPS) { - error = ETOOMANYREFS; - break; + if (imo->imo_num_memberships == imo->imo_max_memberships) { + struct in_multi **nmships, **omships; + size_t newmax; + /* + * Resize the vector to next power-of-two minus 1. If the + * size would exceed the maximum then we know we've really + * run out of entries. Otherwise, we reallocate the vector. + */ + nmships = NULL; + omships = imo->imo_membership; + newmax = ((imo->imo_max_memberships + 1) * 2) - 1; + if (newmax <= IP_MAX_MEMBERSHIPS) { + nmships = (struct in_multi **)malloc( + sizeof(*nmships) * newmax, M_IPMOPTS, + M_NOWAIT|M_ZERO); + if (nmships != NULL) { + bcopy(omships, nmships, + sizeof(*omships) * + imo->imo_max_memberships); + free(omships, M_IPMOPTS); + imo->imo_membership = nmships; + imo->imo_max_memberships = newmax; + } + } + if (nmships == NULL) { + error = ETOOMANYREFS; + break; + } } /* * Everything looks good; add a new record to the multicast @@ -1910,12 +1940,13 @@ ip_setmoptions(optname, imop, m) } /* - * If all options have default values, no need to keep the mbuf. + * If all options have default values, no need to keep the data. */ if (imo->imo_multicast_ifp == NULL && imo->imo_multicast_ttl == IP_DEFAULT_MULTICAST_TTL && imo->imo_multicast_loop == IP_DEFAULT_MULTICAST_LOOP && imo->imo_num_memberships == 0) { + free(imo->imo_membership , M_IPMOPTS); free(*imop, M_IPMOPTS); *imop = NULL; } @@ -1984,6 +2015,7 @@ ip_freemoptions(imo) if (imo != NULL) { for (i = 0; i < imo->imo_num_memberships; ++i) in_delmulti(imo->imo_membership[i]); + free(imo->imo_membership, M_IPMOPTS); free(imo, M_IPMOPTS); } } diff --git a/sys/netinet/ip_var.h b/sys/netinet/ip_var.h index dbe2c64a593..b6ea372229f 100644 --- a/sys/netinet/ip_var.h +++ b/sys/netinet/ip_var.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_var.h,v 1.36 2006/05/29 20:42:27 claudio Exp $ */ +/* $OpenBSD: ip_var.h,v 1.37 2007/09/18 18:56:02 markus Exp $ */ /* $NetBSD: ip_var.h,v 1.16 1996/02/13 23:43:20 christos Exp $ */ /* @@ -96,7 +96,8 @@ struct ip_moptions { u_int8_t imo_multicast_ttl; /* TTL for outgoing multicasts */ u_int8_t imo_multicast_loop; /* 1 => hear sends if a member */ u_int16_t imo_num_memberships; /* no. memberships this socket */ - struct in_multi *imo_membership[IP_MAX_MEMBERSHIPS]; + u_int16_t imo_max_memberships; /* max memberships this socket */ + struct in_multi **imo_membership; /* group memberships */ }; struct ipstat { |