diff options
author | melifaro <melifaro@FreeBSD.org> | 2014-01-18 23:24:51 +0000 |
---|---|---|
committer | melifaro <melifaro@FreeBSD.org> | 2014-01-18 23:24:51 +0000 |
commit | 881c9e28bfecd7527db2dc2584a7ab19e733c821 (patch) | |
tree | 27eae7c12b15b514ef9982e2268330a4e599db09 | |
parent | 978dfbc51760372d61ca97fcdc575a28649eba4d (diff) | |
download | FreeBSD-src-881c9e28bfecd7527db2dc2584a7ab19e733c821.zip FreeBSD-src-881c9e28bfecd7527db2dc2584a7ab19e733c821.tar.gz |
Simplify filling sockaddr_dl structure for if_resolvemulti()
callback providers. link_init_sdl() function can be used to
fill most of the parameters. Use caller stack instead of
allocation / freing memory for each request. Do not drop support
for extra-long (probably non-existing) link-layer protocols by
introducing link_alloc_sdl() (used by if_resolvemulti() callback)
and link_free_sdl() (used by caller).
Since this change breaks KBI, MFC requires slightly different approach
(link_init_sdl() auto-allocating buffer if necessary to handle cases
with unmodified if_resolvemulti() callers).
MFC after: 2 weeks
-rw-r--r-- | sys/net/ieee8023ad_lacp.c | 6 | ||||
-rw-r--r-- | sys/net/if.c | 51 | ||||
-rw-r--r-- | sys/net/if_arcsubr.c | 18 | ||||
-rw-r--r-- | sys/net/if_dl.h | 6 | ||||
-rw-r--r-- | sys/net/if_ethersubr.c | 18 | ||||
-rw-r--r-- | sys/net/if_fddisubr.c | 18 | ||||
-rw-r--r-- | sys/net/if_iso88025subr.c | 18 | ||||
-rw-r--r-- | sys/net/if_lagg.c | 6 | ||||
-rw-r--r-- | sys/ofed/drivers/infiniband/ulp/ipoib/ipoib_main.c | 18 |
9 files changed, 63 insertions, 96 deletions
diff --git a/sys/net/ieee8023ad_lacp.c b/sys/net/ieee8023ad_lacp.c index 1042de6..b023c6c 100644 --- a/sys/net/ieee8023ad_lacp.c +++ b/sys/net/ieee8023ad_lacp.c @@ -522,11 +522,7 @@ lacp_port_create(struct lagg_port *lgp) boolean_t active = TRUE; /* XXX should be configurable */ boolean_t fast = FALSE; /* XXX should be configurable */ - bzero((char *)&sdl, sizeof(sdl)); - sdl.sdl_len = sizeof(sdl); - sdl.sdl_family = AF_LINK; - sdl.sdl_index = ifp->if_index; - sdl.sdl_type = IFT_ETHER; + link_init_sdl(ifp, (struct sockaddr *)&sdl, IFT_ETHER); sdl.sdl_alen = ETHER_ADDR_LEN; bcopy(ðermulticastaddr_slowprotocols, diff --git a/sys/net/if.c b/sys/net/if.c index 75c8e3f..cef3dd3 100644 --- a/sys/net/if.c +++ b/sys/net/if.c @@ -1888,6 +1888,38 @@ link_rtrequest(int cmd, struct rtentry *rt, struct rt_addrinfo *info) } } +struct sockaddr_dl * +link_alloc_sdl(size_t size, int flags) +{ + + return (malloc(size, M_TEMP, flags)); +} + +void +link_free_sdl(struct sockaddr *sa) +{ + free(sa, M_TEMP); +} + +/* + * Fills in given sdl with interface basic info. + * Returns pointer to filled sdl. + */ +struct sockaddr_dl * +link_init_sdl(struct ifnet *ifp, struct sockaddr *paddr, u_char iftype) +{ + struct sockaddr_dl *sdl; + + sdl = (struct sockaddr_dl *)paddr; + memset(sdl, 0, sizeof(struct sockaddr_dl)); + sdl->sdl_len = sizeof(struct sockaddr_dl); + sdl->sdl_family = AF_LINK; + sdl->sdl_index = ifp->if_index; + sdl->sdl_type = iftype; + + return (sdl); +} + /* * Mark an interface down and notify protocols of * the transition. @@ -2938,6 +2970,7 @@ if_addmulti(struct ifnet *ifp, struct sockaddr *sa, { struct ifmultiaddr *ifma, *ll_ifma; struct sockaddr *llsa; + struct sockaddr_dl sdl; int error; /* @@ -2957,12 +2990,18 @@ if_addmulti(struct ifnet *ifp, struct sockaddr *sa, /* * The address isn't already present; resolve the protocol address * into a link layer address, and then look that up, bump its - * refcount or allocate an ifma for that also. If 'llsa' was - * returned, we will need to free it later. + * refcount or allocate an ifma for that also. + * Most link layer resolving functions returns address data which + * fits inside default sockaddr_dl structure. However callback + * can allocate another sockaddr structure, in that case we need to + * free it later. */ llsa = NULL; ll_ifma = NULL; if (ifp->if_resolvemulti != NULL) { + /* Provide called function with buffer size information */ + sdl.sdl_len = sizeof(sdl); + llsa = (struct sockaddr *)&sdl; error = ifp->if_resolvemulti(ifp, &llsa, sa); if (error) goto unlock_out; @@ -3026,14 +3065,14 @@ if_addmulti(struct ifnet *ifp, struct sockaddr *sa, (void) (*ifp->if_ioctl)(ifp, SIOCADDMULTI, 0); } - if (llsa != NULL) - free(llsa, M_IFMADDR); + if ((llsa != NULL) && (llsa != (struct sockaddr *)&sdl)) + link_free_sdl(llsa); return (0); free_llsa_out: - if (llsa != NULL) - free(llsa, M_IFMADDR); + if ((llsa != NULL) && (llsa != (struct sockaddr *)&sdl)) + link_free_sdl(llsa); unlock_out: IF_ADDR_WUNLOCK(ifp); diff --git a/sys/net/if_arcsubr.c b/sys/net/if_arcsubr.c index 49c2dd3..6cec6d9 100644 --- a/sys/net/if_arcsubr.c +++ b/sys/net/if_arcsubr.c @@ -786,14 +786,7 @@ arc_resolvemulti(struct ifnet *ifp, struct sockaddr **llsa, sin = (struct sockaddr_in *)sa; if (!IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) return EADDRNOTAVAIL; - sdl = malloc(sizeof *sdl, M_IFMADDR, - M_NOWAIT | M_ZERO); - if (sdl == NULL) - return ENOMEM; - sdl->sdl_len = sizeof *sdl; - sdl->sdl_family = AF_LINK; - sdl->sdl_index = ifp->if_index; - sdl->sdl_type = IFT_ARCNET; + sdl = link_init_sdl(ifp, *llsa, IFT_ETHER); sdl->sdl_alen = ARC_ADDR_LEN; *LLADDR(sdl) = 0; *llsa = (struct sockaddr *)sdl; @@ -814,14 +807,7 @@ arc_resolvemulti(struct ifnet *ifp, struct sockaddr **llsa, } if (!IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) return EADDRNOTAVAIL; - sdl = malloc(sizeof *sdl, M_IFMADDR, - M_NOWAIT | M_ZERO); - if (sdl == NULL) - return ENOMEM; - sdl->sdl_len = sizeof *sdl; - sdl->sdl_family = AF_LINK; - sdl->sdl_index = ifp->if_index; - sdl->sdl_type = IFT_ARCNET; + sdl = link_init_sdl(ifp, *llsa, IFT_ETHER); sdl->sdl_alen = ARC_ADDR_LEN; *LLADDR(sdl) = 0; *llsa = (struct sockaddr *)sdl; diff --git a/sys/net/if_dl.h b/sys/net/if_dl.h index 64f4b56..8b4e007 100644 --- a/sys/net/if_dl.h +++ b/sys/net/if_dl.h @@ -69,6 +69,12 @@ struct sockaddr_dl { #define LLADDR(s) ((caddr_t)((s)->sdl_data + (s)->sdl_nlen)) #define LLINDEX(s) ((s)->sdl_index) + +struct ifnet; +struct sockaddr_dl *link_alloc_sdl(size_t, int); +void link_free_sdl(struct sockaddr *sa); +struct sockaddr_dl *link_init_sdl(struct ifnet *, struct sockaddr *, u_char); + #ifndef _KERNEL #include <sys/cdefs.h> diff --git a/sys/net/if_ethersubr.c b/sys/net/if_ethersubr.c index 04b94de..ec29b69 100644 --- a/sys/net/if_ethersubr.c +++ b/sys/net/if_ethersubr.c @@ -1168,14 +1168,7 @@ ether_resolvemulti(struct ifnet *ifp, struct sockaddr **llsa, sin = (struct sockaddr_in *)sa; if (!IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) return EADDRNOTAVAIL; - sdl = malloc(sizeof *sdl, M_IFMADDR, - M_NOWAIT|M_ZERO); - if (sdl == NULL) - return ENOMEM; - sdl->sdl_len = sizeof *sdl; - sdl->sdl_family = AF_LINK; - sdl->sdl_index = ifp->if_index; - sdl->sdl_type = IFT_ETHER; + sdl = link_init_sdl(ifp, *llsa, IFT_ETHER); sdl->sdl_alen = ETHER_ADDR_LEN; e_addr = LLADDR(sdl); ETHER_MAP_IP_MULTICAST(&sin->sin_addr, e_addr); @@ -1197,14 +1190,7 @@ ether_resolvemulti(struct ifnet *ifp, struct sockaddr **llsa, } if (!IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) return EADDRNOTAVAIL; - sdl = malloc(sizeof *sdl, M_IFMADDR, - M_NOWAIT|M_ZERO); - if (sdl == NULL) - return (ENOMEM); - sdl->sdl_len = sizeof *sdl; - sdl->sdl_family = AF_LINK; - sdl->sdl_index = ifp->if_index; - sdl->sdl_type = IFT_ETHER; + sdl = link_init_sdl(ifp, *llsa, IFT_ETHER); sdl->sdl_alen = ETHER_ADDR_LEN; e_addr = LLADDR(sdl); ETHER_MAP_IPV6_MULTICAST(&sin6->sin6_addr, e_addr); diff --git a/sys/net/if_fddisubr.c b/sys/net/if_fddisubr.c index 2f03bb7..2bb818b 100644 --- a/sys/net/if_fddisubr.c +++ b/sys/net/if_fddisubr.c @@ -729,14 +729,7 @@ fddi_resolvemulti(ifp, llsa, sa) sin = (struct sockaddr_in *)sa; if (!IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) return (EADDRNOTAVAIL); - sdl = malloc(sizeof *sdl, M_IFMADDR, - M_NOWAIT | M_ZERO); - if (sdl == NULL) - return (ENOMEM); - sdl->sdl_len = sizeof *sdl; - sdl->sdl_family = AF_LINK; - sdl->sdl_index = ifp->if_index; - sdl->sdl_type = IFT_FDDI; + sdl = link_init_sdl(ifp, *llsa, IFT_FDDI); sdl->sdl_nlen = 0; sdl->sdl_alen = FDDI_ADDR_LEN; sdl->sdl_slen = 0; @@ -760,14 +753,7 @@ fddi_resolvemulti(ifp, llsa, sa) } if (!IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) return (EADDRNOTAVAIL); - sdl = malloc(sizeof *sdl, M_IFMADDR, - M_NOWAIT | M_ZERO); - if (sdl == NULL) - return (ENOMEM); - sdl->sdl_len = sizeof *sdl; - sdl->sdl_family = AF_LINK; - sdl->sdl_index = ifp->if_index; - sdl->sdl_type = IFT_FDDI; + sdl = link_init_sdl(ifp, *llsa, IFT_FDDI); sdl->sdl_nlen = 0; sdl->sdl_alen = FDDI_ADDR_LEN; sdl->sdl_slen = 0; diff --git a/sys/net/if_iso88025subr.c b/sys/net/if_iso88025subr.c index 825b220..593c5ab 100644 --- a/sys/net/if_iso88025subr.c +++ b/sys/net/if_iso88025subr.c @@ -721,14 +721,7 @@ iso88025_resolvemulti (ifp, llsa, sa) if (!IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) { return (EADDRNOTAVAIL); } - sdl = malloc(sizeof *sdl, M_IFMADDR, - M_NOWAIT|M_ZERO); - if (sdl == NULL) - return (ENOMEM); - sdl->sdl_len = sizeof *sdl; - sdl->sdl_family = AF_LINK; - sdl->sdl_index = ifp->if_index; - sdl->sdl_type = IFT_ISO88025; + sdl = link_init_sdl(ifp, *llsa, IFT_ISO88025); sdl->sdl_alen = ISO88025_ADDR_LEN; e_addr = LLADDR(sdl); ETHER_MAP_IP_MULTICAST(&sin->sin_addr, e_addr); @@ -751,14 +744,7 @@ iso88025_resolvemulti (ifp, llsa, sa) if (!IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) { return (EADDRNOTAVAIL); } - sdl = malloc(sizeof *sdl, M_IFMADDR, - M_NOWAIT|M_ZERO); - if (sdl == NULL) - return (ENOMEM); - sdl->sdl_len = sizeof *sdl; - sdl->sdl_family = AF_LINK; - sdl->sdl_index = ifp->if_index; - sdl->sdl_type = IFT_ISO88025; + sdl = link_init_sdl(ifp, *llsa, IFT_ISO88025); sdl->sdl_alen = ISO88025_ADDR_LEN; e_addr = LLADDR(sdl); ETHER_MAP_IPV6_MULTICAST(&sin6->sin6_addr, e_addr); diff --git a/sys/net/if_lagg.c b/sys/net/if_lagg.c index beae0b6..c900064 100644 --- a/sys/net/if_lagg.c +++ b/sys/net/if_lagg.c @@ -1214,12 +1214,8 @@ lagg_ether_cmdmulti(struct lagg_port *lp, int set) LAGG_WLOCK_ASSERT(sc); - bzero((char *)&sdl, sizeof(sdl)); - sdl.sdl_len = sizeof(sdl); - sdl.sdl_family = AF_LINK; - sdl.sdl_type = IFT_ETHER; + link_init_sdl(ifp, (struct sockaddr *)&sdl, IFT_ETHER); sdl.sdl_alen = ETHER_ADDR_LEN; - sdl.sdl_index = ifp->if_index; if (set) { TAILQ_FOREACH(ifma, &scifp->if_multiaddrs, ifma_link) { diff --git a/sys/ofed/drivers/infiniband/ulp/ipoib/ipoib_main.c b/sys/ofed/drivers/infiniband/ulp/ipoib/ipoib_main.c index bae1740..52a03d2 100644 --- a/sys/ofed/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/sys/ofed/drivers/infiniband/ulp/ipoib/ipoib_main.c @@ -1490,14 +1490,7 @@ ipoib_resolvemulti(struct ifnet *ifp, struct sockaddr **llsa, sin = (struct sockaddr_in *)sa; if (!IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) return EADDRNOTAVAIL; - sdl = malloc(sizeof *sdl, M_IFMADDR, - M_NOWAIT|M_ZERO); - if (sdl == NULL) - return ENOMEM; - sdl->sdl_len = sizeof *sdl; - sdl->sdl_family = AF_LINK; - sdl->sdl_index = ifp->if_index; - sdl->sdl_type = IFT_INFINIBAND; + sdl = link_init_sdl(ifp, *llsa, IFT_INFINIBAND); sdl->sdl_alen = INFINIBAND_ALEN; e_addr = LLADDR(sdl); ip_ib_mc_map(sin->sin_addr.s_addr, ifp->if_broadcastaddr, @@ -1517,14 +1510,7 @@ ipoib_resolvemulti(struct ifnet *ifp, struct sockaddr **llsa, return EADDRNOTAVAIL; if (!IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) return EADDRNOTAVAIL; - sdl = malloc(sizeof *sdl, M_IFMADDR, - M_NOWAIT|M_ZERO); - if (sdl == NULL) - return (ENOMEM); - sdl->sdl_len = sizeof *sdl; - sdl->sdl_family = AF_LINK; - sdl->sdl_index = ifp->if_index; - sdl->sdl_type = IFT_INFINIBAND; + sdl = link_init_sdl(ifp, *llsa, IFT_INFINIBAND); sdl->sdl_alen = INFINIBAND_ALEN; e_addr = LLADDR(sdl); ipv6_ib_mc_map(&sin6->sin6_addr, ifp->if_broadcastaddr, e_addr); |