Author: melifaro
Date: Sat Jan 18 23:24:51 2014
New Revision: 260870
URL: http://svnweb.freebsd.org/changeset/base/260870

Log:
  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

Modified:
  head/sys/net/ieee8023ad_lacp.c
  head/sys/net/if.c
  head/sys/net/if_arcsubr.c
  head/sys/net/if_dl.h
  head/sys/net/if_ethersubr.c
  head/sys/net/if_fddisubr.c
  head/sys/net/if_iso88025subr.c
  head/sys/net/if_lagg.c
  head/sys/ofed/drivers/infiniband/ulp/ipoib/ipoib_main.c

Modified: head/sys/net/ieee8023ad_lacp.c
==============================================================================
--- head/sys/net/ieee8023ad_lacp.c      Sat Jan 18 22:59:10 2014        
(r260869)
+++ head/sys/net/ieee8023ad_lacp.c      Sat Jan 18 23:24:51 2014        
(r260870)
@@ -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,

Modified: head/sys/net/if.c
==============================================================================
--- head/sys/net/if.c   Sat Jan 18 22:59:10 2014        (r260869)
+++ head/sys/net/if.c   Sat Jan 18 23:24:51 2014        (r260870)
@@ -1888,6 +1888,38 @@ link_rtrequest(int cmd, struct rtentry *
        }
 }
 
+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 so
 {
        struct ifmultiaddr *ifma, *ll_ifma;
        struct sockaddr *llsa;
+       struct sockaddr_dl sdl;
        int error;
 
        /*
@@ -2957,12 +2990,18 @@ if_addmulti(struct ifnet *ifp, struct so
        /*
         * 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 so
                (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);

Modified: head/sys/net/if_arcsubr.c
==============================================================================
--- head/sys/net/if_arcsubr.c   Sat Jan 18 22:59:10 2014        (r260869)
+++ head/sys/net/if_arcsubr.c   Sat Jan 18 23:24:51 2014        (r260870)
@@ -786,14 +786,7 @@ arc_resolvemulti(struct ifnet *ifp, stru
                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, stru
                }
                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;

Modified: head/sys/net/if_dl.h
==============================================================================
--- head/sys/net/if_dl.h        Sat Jan 18 22:59:10 2014        (r260869)
+++ head/sys/net/if_dl.h        Sat Jan 18 23:24:51 2014        (r260870)
@@ -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>

Modified: head/sys/net/if_ethersubr.c
==============================================================================
--- head/sys/net/if_ethersubr.c Sat Jan 18 22:59:10 2014        (r260869)
+++ head/sys/net/if_ethersubr.c Sat Jan 18 23:24:51 2014        (r260870)
@@ -1168,14 +1168,7 @@ ether_resolvemulti(struct ifnet *ifp, st
                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, st
                }
                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);

Modified: head/sys/net/if_fddisubr.c
==============================================================================
--- head/sys/net/if_fddisubr.c  Sat Jan 18 22:59:10 2014        (r260869)
+++ head/sys/net/if_fddisubr.c  Sat Jan 18 23:24:51 2014        (r260870)
@@ -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;

Modified: head/sys/net/if_iso88025subr.c
==============================================================================
--- head/sys/net/if_iso88025subr.c      Sat Jan 18 22:59:10 2014        
(r260869)
+++ head/sys/net/if_iso88025subr.c      Sat Jan 18 23:24:51 2014        
(r260870)
@@ -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);

Modified: head/sys/net/if_lagg.c
==============================================================================
--- head/sys/net/if_lagg.c      Sat Jan 18 22:59:10 2014        (r260869)
+++ head/sys/net/if_lagg.c      Sat Jan 18 23:24:51 2014        (r260870)
@@ -1214,12 +1214,8 @@ lagg_ether_cmdmulti(struct lagg_port *lp
 
        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) {

Modified: head/sys/ofed/drivers/infiniband/ulp/ipoib/ipoib_main.c
==============================================================================
--- head/sys/ofed/drivers/infiniband/ulp/ipoib/ipoib_main.c     Sat Jan 18 
22:59:10 2014        (r260869)
+++ head/sys/ofed/drivers/infiniband/ulp/ipoib/ipoib_main.c     Sat Jan 18 
23:24:51 2014        (r260870)
@@ -1490,14 +1490,7 @@ ipoib_resolvemulti(struct ifnet *ifp, st
                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, st
                        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);
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to