summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormelifaro <melifaro@FreeBSD.org>2014-01-18 23:24:51 +0000
committermelifaro <melifaro@FreeBSD.org>2014-01-18 23:24:51 +0000
commit881c9e28bfecd7527db2dc2584a7ab19e733c821 (patch)
tree27eae7c12b15b514ef9982e2268330a4e599db09
parent978dfbc51760372d61ca97fcdc575a28649eba4d (diff)
downloadFreeBSD-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.c6
-rw-r--r--sys/net/if.c51
-rw-r--r--sys/net/if_arcsubr.c18
-rw-r--r--sys/net/if_dl.h6
-rw-r--r--sys/net/if_ethersubr.c18
-rw-r--r--sys/net/if_fddisubr.c18
-rw-r--r--sys/net/if_iso88025subr.c18
-rw-r--r--sys/net/if_lagg.c6
-rw-r--r--sys/ofed/drivers/infiniband/ulp/ipoib/ipoib_main.c18
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(&ethermulticastaddr_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);
OpenPOWER on IntegriCloud