Tue Feb 21 03:58:24 2017 UTC ()
Replace malloc for DAD with kmem and move them out of the lock for DAD


(ozaki-r)
diff -r1.242 -r1.243 src/sys/netinet/if_arp.c
diff -r1.50 -r1.51 src/sys/netinet/if_inarp.h
diff -r1.136 -r1.137 src/sys/netinet6/nd6_nbr.c

cvs diff -r1.242 -r1.243 src/sys/netinet/if_arp.c (expand / switch to unified diff)

--- src/sys/netinet/if_arp.c 2017/02/11 15:37:30 1.242
+++ src/sys/netinet/if_arp.c 2017/02/21 03:58:23 1.243
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: if_arp.c,v 1.242 2017/02/11 15:37:30 roy Exp $ */ 1/* $NetBSD: if_arp.c,v 1.243 2017/02/21 03:58:23 ozaki-r Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 1998, 2000, 2008 The NetBSD Foundation, Inc. 4 * Copyright (c) 1998, 2000, 2008 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to The NetBSD Foundation 7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Public Access Networks Corporation ("Panix"). It was developed under 8 * by Public Access Networks Corporation ("Panix"). It was developed under
9 * contract to Panix by Eric Haszlakiewicz and Thor Lancelot Simon. 9 * contract to Panix by Eric Haszlakiewicz and Thor Lancelot Simon.
10 * 10 *
11 * Redistribution and use in source and binary forms, with or without 11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions 12 * modification, are permitted provided that the following conditions
13 * are met: 13 * are met:
14 * 1. Redistributions of source code must retain the above copyright 14 * 1. Redistributions of source code must retain the above copyright
@@ -58,43 +58,43 @@ @@ -58,43 +58,43 @@
58 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 58 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
59 * SUCH DAMAGE. 59 * SUCH DAMAGE.
60 * 60 *
61 * @(#)if_ether.c 8.2 (Berkeley) 9/26/94 61 * @(#)if_ether.c 8.2 (Berkeley) 9/26/94
62 */ 62 */
63 63
64/* 64/*
65 * Ethernet address resolution protocol. 65 * Ethernet address resolution protocol.
66 * TODO: 66 * TODO:
67 * add "inuse/lock" bit (or ref. count) along with valid bit 67 * add "inuse/lock" bit (or ref. count) along with valid bit
68 */ 68 */
69 69
70#include <sys/cdefs.h> 70#include <sys/cdefs.h>
71__KERNEL_RCSID(0, "$NetBSD: if_arp.c,v 1.242 2017/02/11 15:37:30 roy Exp $"); 71__KERNEL_RCSID(0, "$NetBSD: if_arp.c,v 1.243 2017/02/21 03:58:23 ozaki-r Exp $");
72 72
73#ifdef _KERNEL_OPT 73#ifdef _KERNEL_OPT
74#include "opt_ddb.h" 74#include "opt_ddb.h"
75#include "opt_inet.h" 75#include "opt_inet.h"
76#include "opt_net_mpsafe.h" 76#include "opt_net_mpsafe.h"
77#endif 77#endif
78 78
79#ifdef INET 79#ifdef INET
80 80
81#include "arp.h" 81#include "arp.h"
82#include "bridge.h" 82#include "bridge.h"
83 83
84#include <sys/param.h> 84#include <sys/param.h>
85#include <sys/systm.h> 85#include <sys/systm.h>
86#include <sys/callout.h> 86#include <sys/callout.h>
87#include <sys/malloc.h> 87#include <sys/kmem.h>
88#include <sys/mbuf.h> 88#include <sys/mbuf.h>
89#include <sys/socket.h> 89#include <sys/socket.h>
90#include <sys/time.h> 90#include <sys/time.h>
91#include <sys/timetc.h> 91#include <sys/timetc.h>
92#include <sys/kernel.h> 92#include <sys/kernel.h>
93#include <sys/errno.h> 93#include <sys/errno.h>
94#include <sys/ioctl.h> 94#include <sys/ioctl.h>
95#include <sys/syslog.h> 95#include <sys/syslog.h>
96#include <sys/proc.h> 96#include <sys/proc.h>
97#include <sys/protosw.h> 97#include <sys/protosw.h>
98#include <sys/domain.h> 98#include <sys/domain.h>
99#include <sys/sysctl.h> 99#include <sys/sysctl.h>
100#include <sys/socketvar.h> 100#include <sys/socketvar.h>
@@ -1505,27 +1505,26 @@ arp_ifinit(struct ifnet *ifp, struct ifa @@ -1505,27 +1505,26 @@ arp_ifinit(struct ifnet *ifp, struct ifa
1505} 1505}
1506 1506
1507TAILQ_HEAD(dadq_head, dadq); 1507TAILQ_HEAD(dadq_head, dadq);
1508struct dadq { 1508struct dadq {
1509 TAILQ_ENTRY(dadq) dad_list; 1509 TAILQ_ENTRY(dadq) dad_list;
1510 struct ifaddr *dad_ifa; 1510 struct ifaddr *dad_ifa;
1511 int dad_count; /* max ARP to send */ 1511 int dad_count; /* max ARP to send */
1512 int dad_arp_tcount; /* # of trials to send ARP */ 1512 int dad_arp_tcount; /* # of trials to send ARP */
1513 int dad_arp_ocount; /* ARP sent so far */ 1513 int dad_arp_ocount; /* ARP sent so far */
1514 int dad_arp_announce; /* max ARP announcements */ 1514 int dad_arp_announce; /* max ARP announcements */
1515 int dad_arp_acount; /* # of announcements */ 1515 int dad_arp_acount; /* # of announcements */
1516 struct callout dad_timer_ch; 1516 struct callout dad_timer_ch;
1517}; 1517};
1518MALLOC_JUSTDEFINE(M_IPARP, "ARP DAD", "ARP DAD Structure"); 
1519 1518
1520static struct dadq_head dadq; 1519static struct dadq_head dadq;
1521static int dad_init = 0; 1520static int dad_init = 0;
1522static int dad_maxtry = 15; /* max # of *tries* to transmit DAD packet */ 1521static int dad_maxtry = 15; /* max # of *tries* to transmit DAD packet */
1523static kmutex_t arp_dad_lock; 1522static kmutex_t arp_dad_lock;
1524 1523
1525static struct dadq * 1524static struct dadq *
1526arp_dad_find(struct ifaddr *ifa) 1525arp_dad_find(struct ifaddr *ifa)
1527{ 1526{
1528 struct dadq *dp; 1527 struct dadq *dp;
1529 1528
1530 KASSERT(mutex_owned(&arp_dad_lock)); 1529 KASSERT(mutex_owned(&arp_dad_lock));
1531 1530
@@ -1603,48 +1602,50 @@ arp_dad_start(struct ifaddr *ifa) @@ -1603,48 +1602,50 @@ arp_dad_start(struct ifaddr *ifa)
1603 ifa->ifa_ifp ? if_name(ifa->ifa_ifp) : "???"); 1602 ifa->ifa_ifp ? if_name(ifa->ifa_ifp) : "???");
1604 return; 1603 return;
1605 } 1604 }
1606 if (!ip_dad_count) { 1605 if (!ip_dad_count) {
1607 ia->ia4_flags &= ~IN_IFF_TENTATIVE; 1606 ia->ia4_flags &= ~IN_IFF_TENTATIVE;
1608 rt_newaddrmsg(RTM_NEWADDR, ifa, 0, NULL); 1607 rt_newaddrmsg(RTM_NEWADDR, ifa, 0, NULL);
1609 arpannounce1(ifa); 1608 arpannounce1(ifa);
1610 return; 1609 return;
1611 } 1610 }
1612 KASSERT(ifa->ifa_ifp != NULL); 1611 KASSERT(ifa->ifa_ifp != NULL);
1613 if (!(ifa->ifa_ifp->if_flags & IFF_UP)) 1612 if (!(ifa->ifa_ifp->if_flags & IFF_UP))
1614 return; 1613 return;
1615 1614
 1615 dp = kmem_intr_alloc(sizeof(*dp), KM_NOSLEEP);
 1616
1616 mutex_enter(&arp_dad_lock); 1617 mutex_enter(&arp_dad_lock);
1617 if (arp_dad_find(ifa) != NULL) { 1618 if (arp_dad_find(ifa) != NULL) {
1618 mutex_exit(&arp_dad_lock); 1619 mutex_exit(&arp_dad_lock);
1619 /* DAD already in progress */ 1620 /* DAD already in progress */
 1621 if (dp != NULL)
 1622 kmem_intr_free(dp, sizeof(*dp));
1620 return; 1623 return;
1621 } 1624 }
1622 1625
1623 dp = malloc(sizeof(*dp), M_IPARP, M_NOWAIT); 
1624 if (dp == NULL) { 1626 if (dp == NULL) {
1625 mutex_exit(&arp_dad_lock); 1627 mutex_exit(&arp_dad_lock);
1626 log(LOG_ERR, "%s: memory allocation failed for %s(%s)\n", 1628 log(LOG_ERR, "%s: memory allocation failed for %s(%s)\n",
1627 __func__, in_fmtaddr(ipbuf, ia->ia_addr.sin_addr), 1629 __func__, in_fmtaddr(ipbuf, ia->ia_addr.sin_addr),
1628 ifa->ifa_ifp ? if_name(ifa->ifa_ifp) : "???"); 1630 ifa->ifa_ifp ? if_name(ifa->ifa_ifp) : "???");
1629 return; 1631 return;
1630 } 1632 }
1631 memset(dp, 0, sizeof(*dp)); 
1632 callout_init(&dp->dad_timer_ch, CALLOUT_MPSAFE); 
1633 1633
1634 /* 1634 /*
1635 * Send ARP packet for DAD, ip_dad_count times. 1635 * Send ARP packet for DAD, ip_dad_count times.
1636 * Note that we must delay the first transmission. 1636 * Note that we must delay the first transmission.
1637 */ 1637 */
 1638 callout_init(&dp->dad_timer_ch, CALLOUT_MPSAFE);
1638 dp->dad_ifa = ifa; 1639 dp->dad_ifa = ifa;
1639 ifaref(ifa); /* just for safety */ 1640 ifaref(ifa); /* just for safety */
1640 dp->dad_count = ip_dad_count; 1641 dp->dad_count = ip_dad_count;
1641 dp->dad_arp_announce = 0; /* Will be set when starting to announce */ 1642 dp->dad_arp_announce = 0; /* Will be set when starting to announce */
1642 dp->dad_arp_acount = dp->dad_arp_ocount = dp->dad_arp_tcount = 0; 1643 dp->dad_arp_acount = dp->dad_arp_ocount = dp->dad_arp_tcount = 0;
1643 TAILQ_INSERT_TAIL(&dadq, (struct dadq *)dp, dad_list); 1644 TAILQ_INSERT_TAIL(&dadq, (struct dadq *)dp, dad_list);
1644 1645
1645 ARPLOG(LOG_DEBUG, "%s: starting DAD for %s\n", if_name(ifa->ifa_ifp), 1646 ARPLOG(LOG_DEBUG, "%s: starting DAD for %s\n", if_name(ifa->ifa_ifp),
1646 ARPLOGADDR(ia->ia_addr.sin_addr)); 1647 ARPLOGADDR(ia->ia_addr.sin_addr));
1647 1648
1648 arp_dad_starttimer(dp, cprng_fast32() % (PROBE_WAIT * hz)); 1649 arp_dad_starttimer(dp, cprng_fast32() % (PROBE_WAIT * hz));
1649 1650
1650 mutex_exit(&arp_dad_lock); 1651 mutex_exit(&arp_dad_lock);
@@ -1665,37 +1666,37 @@ arp_dad_stop(struct ifaddr *ifa) @@ -1665,37 +1666,37 @@ arp_dad_stop(struct ifaddr *ifa)
1665 dp = arp_dad_find(ifa); 1666 dp = arp_dad_find(ifa);
1666 if (dp == NULL) { 1667 if (dp == NULL) {
1667 mutex_exit(&arp_dad_lock); 1668 mutex_exit(&arp_dad_lock);
1668 /* DAD wasn't started yet */ 1669 /* DAD wasn't started yet */
1669 return; 1670 return;
1670 } 1671 }
1671 1672
1672 /* Prevent the timer from running anymore. */ 1673 /* Prevent the timer from running anymore. */
1673 TAILQ_REMOVE(&dadq, dp, dad_list); 1674 TAILQ_REMOVE(&dadq, dp, dad_list);
1674 mutex_exit(&arp_dad_lock); 1675 mutex_exit(&arp_dad_lock);
1675 1676
1676 arp_dad_stoptimer(dp); 1677 arp_dad_stoptimer(dp);
1677 1678
1678 free(dp, M_IPARP); 1679 kmem_intr_free(dp, sizeof(*dp));
1679 dp = NULL; 
1680 ifafree(ifa); 1680 ifafree(ifa);
1681} 1681}
1682 1682
1683static void 1683static void
1684arp_dad_timer(struct ifaddr *ifa) 1684arp_dad_timer(struct ifaddr *ifa)
1685{ 1685{
1686 struct in_ifaddr *ia = (struct in_ifaddr *)ifa; 1686 struct in_ifaddr *ia = (struct in_ifaddr *)ifa;
1687 struct dadq *dp; 1687 struct dadq *dp;
1688 char ipbuf[INET_ADDRSTRLEN]; 1688 char ipbuf[INET_ADDRSTRLEN];
 1689 bool need_free = false;
1689 1690
1690#ifndef NET_MPSAFE 1691#ifndef NET_MPSAFE
1691 mutex_enter(softnet_lock); 1692 mutex_enter(softnet_lock);
1692 KERNEL_LOCK(1, NULL); 1693 KERNEL_LOCK(1, NULL);
1693#endif 1694#endif
1694 mutex_enter(&arp_dad_lock); 1695 mutex_enter(&arp_dad_lock);
1695 1696
1696 /* Sanity check */ 1697 /* Sanity check */
1697 if (ia == NULL) { 1698 if (ia == NULL) {
1698 log(LOG_ERR, "%s: called with null parameter\n", __func__); 1699 log(LOG_ERR, "%s: called with null parameter\n", __func__);
1699 goto done; 1700 goto done;
1700 } 1701 }
1701 dp = arp_dad_find(ifa); 1702 dp = arp_dad_find(ifa);
@@ -1713,29 +1714,27 @@ arp_dad_timer(struct ifaddr *ifa) @@ -1713,29 +1714,27 @@ arp_dad_timer(struct ifaddr *ifa)
1713 { 1714 {
1714 log(LOG_ERR, "%s: called with non-tentative address %s(%s)\n", 1715 log(LOG_ERR, "%s: called with non-tentative address %s(%s)\n",
1715 __func__, in_fmtaddr(ipbuf, ia->ia_addr.sin_addr), 1716 __func__, in_fmtaddr(ipbuf, ia->ia_addr.sin_addr),
1716 ifa->ifa_ifp ? if_name(ifa->ifa_ifp) : "???"); 1717 ifa->ifa_ifp ? if_name(ifa->ifa_ifp) : "???");
1717 goto done; 1718 goto done;
1718 } 1719 }
1719 1720
1720 /* timeouted with IFF_{RUNNING,UP} check */ 1721 /* timeouted with IFF_{RUNNING,UP} check */
1721 if (dp->dad_arp_tcount > dad_maxtry) { 1722 if (dp->dad_arp_tcount > dad_maxtry) {
1722 ARPLOG(LOG_INFO, "%s: could not run DAD, driver problem?\n", 1723 ARPLOG(LOG_INFO, "%s: could not run DAD, driver problem?\n",
1723 if_name(ifa->ifa_ifp)); 1724 if_name(ifa->ifa_ifp));
1724 1725
1725 TAILQ_REMOVE(&dadq, dp, dad_list); 1726 TAILQ_REMOVE(&dadq, dp, dad_list);
1726 free(dp, M_IPARP); 1727 need_free = true;
1727 dp = NULL; 
1728 ifafree(ifa); 
1729 goto done; 1728 goto done;
1730 } 1729 }
1731 1730
1732 /* Need more checks? */ 1731 /* Need more checks? */
1733 if (dp->dad_arp_ocount < dp->dad_count) { 1732 if (dp->dad_arp_ocount < dp->dad_count) {
1734 int adelay; 1733 int adelay;
1735 1734
1736 /* 1735 /*
1737 * We have more ARP to go. Send ARP packet for DAD. 1736 * We have more ARP to go. Send ARP packet for DAD.
1738 */ 1737 */
1739 arp_dad_output(dp, ifa); 1738 arp_dad_output(dp, ifa);
1740 if (dp->dad_arp_ocount < dp->dad_count) 1739 if (dp->dad_arp_ocount < dp->dad_count)
1741 adelay = (PROBE_MIN * hz) + 1740 adelay = (PROBE_MIN * hz) +
@@ -1764,32 +1763,35 @@ announce: @@ -1764,32 +1763,35 @@ announce:
1764 */ 1763 */
1765 arpannounce1(ifa); 1764 arpannounce1(ifa);
1766 dp->dad_arp_acount++; 1765 dp->dad_arp_acount++;
1767 if (dp->dad_arp_acount < dp->dad_arp_announce) { 1766 if (dp->dad_arp_acount < dp->dad_arp_announce) {
1768 arp_dad_starttimer(dp, ANNOUNCE_INTERVAL * hz); 1767 arp_dad_starttimer(dp, ANNOUNCE_INTERVAL * hz);
1769 goto done; 1768 goto done;
1770 } 1769 }
1771 ARPLOG(LOG_DEBUG, 1770 ARPLOG(LOG_DEBUG,
1772 "%s: ARP announcement complete for %s\n", 1771 "%s: ARP announcement complete for %s\n",
1773 if_name(ifa->ifa_ifp), ARPLOGADDR(ia->ia_addr.sin_addr)); 1772 if_name(ifa->ifa_ifp), ARPLOGADDR(ia->ia_addr.sin_addr));
1774 } 1773 }
1775 1774
1776 TAILQ_REMOVE(&dadq, dp, dad_list); 1775 TAILQ_REMOVE(&dadq, dp, dad_list);
1777 free(dp, M_IPARP); 1776 need_free = true;
1778 dp = NULL; 
1779 ifafree(ifa); 
1780 
1781done: 1777done:
1782 mutex_exit(&arp_dad_lock); 1778 mutex_exit(&arp_dad_lock);
 1779
 1780 if (need_free) {
 1781 kmem_intr_free(dp, sizeof(*dp));
 1782 ifafree(ifa);
 1783 }
 1784
1783#ifndef NET_MPSAFE 1785#ifndef NET_MPSAFE
1784 KERNEL_UNLOCK_ONE(NULL); 1786 KERNEL_UNLOCK_ONE(NULL);
1785 mutex_exit(softnet_lock); 1787 mutex_exit(softnet_lock);
1786#endif 1788#endif
1787} 1789}
1788 1790
1789static void 1791static void
1790arp_dad_duplicated(struct ifaddr *ifa, const char *sha) 1792arp_dad_duplicated(struct ifaddr *ifa, const char *sha)
1791{ 1793{
1792 struct in_ifaddr *ia = (struct in_ifaddr *)ifa; 1794 struct in_ifaddr *ia = (struct in_ifaddr *)ifa;
1793 struct ifnet *ifp = ifa->ifa_ifp; 1795 struct ifnet *ifp = ifa->ifa_ifp;
1794 char ipbuf[INET_ADDRSTRLEN]; 1796 char ipbuf[INET_ADDRSTRLEN];
1795 const char *iastr; 1797 const char *iastr;

cvs diff -r1.50 -r1.51 src/sys/netinet/if_inarp.h (expand / switch to unified diff)

--- src/sys/netinet/if_inarp.h 2016/10/11 12:32:30 1.50
+++ src/sys/netinet/if_inarp.h 2017/02/21 03:58:24 1.51
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: if_inarp.h,v 1.50 2016/10/11 12:32:30 roy Exp $ */ 1/* $NetBSD: if_inarp.h,v 1.51 2017/02/21 03:58:24 ozaki-r Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1982, 1986, 1993 4 * Copyright (c) 1982, 1986, 1993
5 * The Regents of the University of California. All rights reserved. 5 * The Regents of the University of California. All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
@@ -59,29 +59,26 @@ struct sockaddr_inarp { @@ -59,29 +59,26 @@ struct sockaddr_inarp {
59 59
60/* ARP timings from RFC5227 */ 60/* ARP timings from RFC5227 */
61#define PROBE_WAIT 1 61#define PROBE_WAIT 1
62#define PROBE_NUM 3 62#define PROBE_NUM 3
63#define PROBE_MIN 1 63#define PROBE_MIN 1
64#define PROBE_MAX 2 64#define PROBE_MAX 2
65#define ANNOUNCE_WAIT 2 65#define ANNOUNCE_WAIT 2
66#define ANNOUNCE_NUM 2 66#define ANNOUNCE_NUM 2
67#define ANNOUNCE_INTERVAL 2 67#define ANNOUNCE_INTERVAL 2
68#define MAX_CONFLICTS 10 68#define MAX_CONFLICTS 10
69#define RATE_LIMIT_INTERVAL 60 69#define RATE_LIMIT_INTERVAL 60
70#define DEFEND_INTERVAL 10 70#define DEFEND_INTERVAL 10
71 71
72#include <sys/malloc.h> 
73MALLOC_DECLARE(M_IPARP); 
74 
75extern struct ifqueue arpintrq; 72extern struct ifqueue arpintrq;
76void arp_ifinit(struct ifnet *, struct ifaddr *); 73void arp_ifinit(struct ifnet *, struct ifaddr *);
77void arp_rtrequest(int, struct rtentry *, const struct rt_addrinfo *); 74void arp_rtrequest(int, struct rtentry *, const struct rt_addrinfo *);
78int arpresolve(struct ifnet *, const struct rtentry *, struct mbuf *, 75int arpresolve(struct ifnet *, const struct rtentry *, struct mbuf *,
79 const struct sockaddr *, void *, size_t); 76 const struct sockaddr *, void *, size_t);
80void arpintr(void); 77void arpintr(void);
81void arpannounce(struct ifnet *, struct ifaddr *, const uint8_t *); 78void arpannounce(struct ifnet *, struct ifaddr *, const uint8_t *);
82void arp_drain(void); 79void arp_drain(void);
83int arpioctl(u_long, void *); 80int arpioctl(u_long, void *);
84void arpwhohas(struct ifnet *, struct in_addr *); 81void arpwhohas(struct ifnet *, struct in_addr *);
85 82
86void revarpinput(struct mbuf *); 83void revarpinput(struct mbuf *);
87int revarpwhoarewe(struct ifnet *, struct in_addr *, struct in_addr *); 84int revarpwhoarewe(struct ifnet *, struct in_addr *, struct in_addr *);

cvs diff -r1.136 -r1.137 src/sys/netinet6/nd6_nbr.c (expand / switch to unified diff)

--- src/sys/netinet6/nd6_nbr.c 2017/01/16 15:44:47 1.136
+++ src/sys/netinet6/nd6_nbr.c 2017/02/21 03:58:24 1.137
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: nd6_nbr.c,v 1.136 2017/01/16 15:44:47 christos Exp $ */ 1/* $NetBSD: nd6_nbr.c,v 1.137 2017/02/21 03:58:24 ozaki-r Exp $ */
2/* $KAME: nd6_nbr.c,v 1.61 2001/02/10 16:06:14 jinmei Exp $ */ 2/* $KAME: nd6_nbr.c,v 1.61 2001/02/10 16:06:14 jinmei Exp $ */
3 3
4/* 4/*
5 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 5 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
6 * All rights reserved. 6 * All rights reserved.
7 * 7 *
8 * Redistribution and use in source and binary forms, with or without 8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions 9 * modification, are permitted provided that the following conditions
10 * are met: 10 * are met:
11 * 1. Redistributions of source code must retain the above copyright 11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer. 12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright 13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the 14 * notice, this list of conditions and the following disclaimer in the
@@ -21,36 +21,36 @@ @@ -21,36 +21,36 @@
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE. 30 * SUCH DAMAGE.
31 */ 31 */
32 32
33#include <sys/cdefs.h> 33#include <sys/cdefs.h>
34__KERNEL_RCSID(0, "$NetBSD: nd6_nbr.c,v 1.136 2017/01/16 15:44:47 christos Exp $"); 34__KERNEL_RCSID(0, "$NetBSD: nd6_nbr.c,v 1.137 2017/02/21 03:58:24 ozaki-r Exp $");
35 35
36#ifdef _KERNEL_OPT 36#ifdef _KERNEL_OPT
37#include "opt_inet.h" 37#include "opt_inet.h"
38#include "opt_net_mpsafe.h" 38#include "opt_net_mpsafe.h"
39#endif 39#endif
40 40
41#include <sys/param.h> 41#include <sys/param.h>
42#include <sys/systm.h> 42#include <sys/systm.h>
43#include <sys/malloc.h> 43#include <sys/kmem.h>
44#include <sys/mbuf.h> 44#include <sys/mbuf.h>
45#include <sys/socket.h> 45#include <sys/socket.h>
46#include <sys/socketvar.h> 46#include <sys/socketvar.h>
47#include <sys/sockio.h> 47#include <sys/sockio.h>
48#include <sys/time.h> 48#include <sys/time.h>
49#include <sys/kernel.h> 49#include <sys/kernel.h>
50#include <sys/errno.h> 50#include <sys/errno.h>
51#include <sys/ioctl.h> 51#include <sys/ioctl.h>
52#include <sys/syslog.h> 52#include <sys/syslog.h>
53#include <sys/queue.h> 53#include <sys/queue.h>
54#include <sys/callout.h> 54#include <sys/callout.h>
55 55
56#include <net/if.h> 56#include <net/if.h>
@@ -1144,51 +1144,53 @@ nd6_dad_start(struct ifaddr *ifa, int xt @@ -1144,51 +1144,53 @@ nd6_dad_start(struct ifaddr *ifa, int xt
1144 IN6_PRINT(ip6buf, &ia->ia_addr.sin6_addr), 1144 IN6_PRINT(ip6buf, &ia->ia_addr.sin6_addr),
1145 ifa->ifa_ifp ? if_name(ifa->ifa_ifp) : "???"); 1145 ifa->ifa_ifp ? if_name(ifa->ifa_ifp) : "???");
1146 return; 1146 return;
1147 } 1147 }
1148 if (ia->ia6_flags & IN6_IFF_ANYCAST || !ip6_dad_count) { 1148 if (ia->ia6_flags & IN6_IFF_ANYCAST || !ip6_dad_count) {
1149 ia->ia6_flags &= ~IN6_IFF_TENTATIVE; 1149 ia->ia6_flags &= ~IN6_IFF_TENTATIVE;
1150 rt_newaddrmsg(RTM_NEWADDR, ifa, 0, NULL); 1150 rt_newaddrmsg(RTM_NEWADDR, ifa, 0, NULL);
1151 return; 1151 return;
1152 } 1152 }
1153 KASSERT(ifa->ifa_ifp != NULL); 1153 KASSERT(ifa->ifa_ifp != NULL);
1154 if (!(ifa->ifa_ifp->if_flags & IFF_UP)) 1154 if (!(ifa->ifa_ifp->if_flags & IFF_UP))
1155 return; 1155 return;
1156 1156
 1157 dp = kmem_intr_alloc(sizeof(*dp), KM_NOSLEEP);
 1158
1157 mutex_enter(&nd6_dad_lock); 1159 mutex_enter(&nd6_dad_lock);
1158 if (nd6_dad_find(ifa) != NULL) { 1160 if (nd6_dad_find(ifa) != NULL) {
1159 mutex_exit(&nd6_dad_lock); 1161 mutex_exit(&nd6_dad_lock);
1160 /* DAD already in progress */ 1162 /* DAD already in progress */
 1163 if (dp != NULL)
 1164 kmem_intr_free(dp, sizeof(*dp));
1161 return; 1165 return;
1162 } 1166 }
1163 1167
1164 dp = malloc(sizeof(*dp), M_IP6NDP, M_NOWAIT); 
1165 if (dp == NULL) { 1168 if (dp == NULL) {
1166 mutex_exit(&nd6_dad_lock); 1169 mutex_exit(&nd6_dad_lock);
1167 log(LOG_ERR, "nd6_dad_start: memory allocation failed for " 1170 log(LOG_ERR, "nd6_dad_start: memory allocation failed for "
1168 "%s(%s)\n", 1171 "%s(%s)\n",
1169 IN6_PRINT(ip6buf, &ia->ia_addr.sin6_addr), 1172 IN6_PRINT(ip6buf, &ia->ia_addr.sin6_addr),
1170 ifa->ifa_ifp ? if_name(ifa->ifa_ifp) : "???"); 1173 ifa->ifa_ifp ? if_name(ifa->ifa_ifp) : "???");
1171 return; 1174 return;
1172 } 1175 }
1173 memset(dp, 0, sizeof(*dp)); 
1174 callout_init(&dp->dad_timer_ch, CALLOUT_MPSAFE); 
1175 1176
1176 /* 1177 /*
1177 * Send NS packet for DAD, ip6_dad_count times. 1178 * Send NS packet for DAD, ip6_dad_count times.
1178 * Note that we must delay the first transmission, if this is the 1179 * Note that we must delay the first transmission, if this is the
1179 * first packet to be sent from the interface after interface 1180 * first packet to be sent from the interface after interface
1180 * (re)initialization. 1181 * (re)initialization.
1181 */ 1182 */
 1183 callout_init(&dp->dad_timer_ch, CALLOUT_MPSAFE);
1182 dp->dad_ifa = ifa; 1184 dp->dad_ifa = ifa;
1183 ifaref(ifa); /* just for safety */ 1185 ifaref(ifa); /* just for safety */
1184 dp->dad_count = ip6_dad_count; 1186 dp->dad_count = ip6_dad_count;
1185 dp->dad_ns_icount = dp->dad_na_icount = 0; 1187 dp->dad_ns_icount = dp->dad_na_icount = 0;
1186 dp->dad_ns_ocount = dp->dad_ns_tcount = 0; 1188 dp->dad_ns_ocount = dp->dad_ns_tcount = 0;
1187 TAILQ_INSERT_TAIL(&dadq, (struct dadq *)dp, dad_list); 1189 TAILQ_INSERT_TAIL(&dadq, (struct dadq *)dp, dad_list);
1188 1190
1189 nd6log(LOG_DEBUG, "%s: starting DAD for %s\n", if_name(ifa->ifa_ifp), 1191 nd6log(LOG_DEBUG, "%s: starting DAD for %s\n", if_name(ifa->ifa_ifp),
1190 IN6_PRINT(ip6buf, &ia->ia_addr.sin6_addr)); 1192 IN6_PRINT(ip6buf, &ia->ia_addr.sin6_addr));
1191 1193
1192 if (xtick == 0) { 1194 if (xtick == 0) {
1193 nd6_dad_ns_output(dp, ifa); 1195 nd6_dad_ns_output(dp, ifa);
1194 nd6_dad_starttimer(dp, 1196 nd6_dad_starttimer(dp,
@@ -1213,38 +1215,38 @@ nd6_dad_stop(struct ifaddr *ifa) @@ -1213,38 +1215,38 @@ nd6_dad_stop(struct ifaddr *ifa)
1213 dp = nd6_dad_find(ifa); 1215 dp = nd6_dad_find(ifa);
1214 if (dp == NULL) { 1216 if (dp == NULL) {
1215 mutex_exit(&nd6_dad_lock); 1217 mutex_exit(&nd6_dad_lock);
1216 /* DAD wasn't started yet */ 1218 /* DAD wasn't started yet */
1217 return; 1219 return;
1218 } 1220 }
1219 1221
1220 /* Prevent the timer from running anymore. */ 1222 /* Prevent the timer from running anymore. */
1221 TAILQ_REMOVE(&dadq, dp, dad_list); 1223 TAILQ_REMOVE(&dadq, dp, dad_list);
1222 mutex_exit(&nd6_dad_lock); 1224 mutex_exit(&nd6_dad_lock);
1223 1225
1224 nd6_dad_stoptimer(dp); 1226 nd6_dad_stoptimer(dp);
1225 1227
1226 free(dp, M_IP6NDP); 1228 kmem_intr_free(dp, sizeof(*dp));
1227 dp = NULL; 
1228 ifafree(ifa); 1229 ifafree(ifa);
1229} 1230}
1230 1231
1231static void 1232static void
1232nd6_dad_timer(struct ifaddr *ifa) 1233nd6_dad_timer(struct ifaddr *ifa)
1233{ 1234{
1234 struct in6_ifaddr *ia = (struct in6_ifaddr *)ifa; 1235 struct in6_ifaddr *ia = (struct in6_ifaddr *)ifa;
1235 struct dadq *dp; 1236 struct dadq *dp;
1236 int duplicate = 0; 1237 int duplicate = 0;
1237 char ip6buf[INET6_ADDRSTRLEN]; 1238 char ip6buf[INET6_ADDRSTRLEN];
 1239 bool need_free = false;
1238 1240
1239#ifndef NET_MPSAFE 1241#ifndef NET_MPSAFE
1240 mutex_enter(softnet_lock); 1242 mutex_enter(softnet_lock);
1241 KERNEL_LOCK(1, NULL); 1243 KERNEL_LOCK(1, NULL);
1242#endif 1244#endif
1243 mutex_enter(&nd6_dad_lock); 1245 mutex_enter(&nd6_dad_lock);
1244 1246
1245 /* Sanity check */ 1247 /* Sanity check */
1246 if (ia == NULL) { 1248 if (ia == NULL) {
1247 log(LOG_ERR, "nd6_dad_timer: called with null parameter\n"); 1249 log(LOG_ERR, "nd6_dad_timer: called with null parameter\n");
1248 goto done; 1250 goto done;
1249 } 1251 }
1250 dp = nd6_dad_find(ifa); 1252 dp = nd6_dad_find(ifa);
@@ -1263,29 +1265,27 @@ nd6_dad_timer(struct ifaddr *ifa) @@ -1263,29 +1265,27 @@ nd6_dad_timer(struct ifaddr *ifa)
1263 log(LOG_ERR, "nd6_dad_timer: called with non-tentative address " 1265 log(LOG_ERR, "nd6_dad_timer: called with non-tentative address "
1264 "%s(%s)\n", 1266 "%s(%s)\n",
1265 IN6_PRINT(ip6buf, &ia->ia_addr.sin6_addr), 1267 IN6_PRINT(ip6buf, &ia->ia_addr.sin6_addr),
1266 ifa->ifa_ifp ? if_name(ifa->ifa_ifp) : "???"); 1268 ifa->ifa_ifp ? if_name(ifa->ifa_ifp) : "???");
1267 goto done; 1269 goto done;
1268 } 1270 }
1269 1271
1270 /* timeouted with IFF_{RUNNING,UP} check */ 1272 /* timeouted with IFF_{RUNNING,UP} check */
1271 if (dp->dad_ns_tcount > dad_maxtry) { 1273 if (dp->dad_ns_tcount > dad_maxtry) {
1272 nd6log(LOG_INFO, "%s: could not run DAD, driver problem?\n", 1274 nd6log(LOG_INFO, "%s: could not run DAD, driver problem?\n",
1273 if_name(ifa->ifa_ifp)); 1275 if_name(ifa->ifa_ifp));
1274 1276
1275 TAILQ_REMOVE(&dadq, dp, dad_list); 1277 TAILQ_REMOVE(&dadq, dp, dad_list);
1276 free(dp, M_IP6NDP); 1278 need_free = true;
1277 dp = NULL; 
1278 ifafree(ifa); 
1279 goto done; 1279 goto done;
1280 } 1280 }
1281 1281
1282 /* Need more checks? */ 1282 /* Need more checks? */
1283 if (dp->dad_ns_ocount < dp->dad_count) { 1283 if (dp->dad_ns_ocount < dp->dad_count) {
1284 /* 1284 /*
1285 * We have more NS to go. Send NS packet for DAD. 1285 * We have more NS to go. Send NS packet for DAD.
1286 */ 1286 */
1287 nd6_dad_ns_output(dp, ifa); 1287 nd6_dad_ns_output(dp, ifa);
1288 nd6_dad_starttimer(dp, 1288 nd6_dad_starttimer(dp,
1289 (long)ND_IFINFO(ifa->ifa_ifp)->retrans * hz / 1000); 1289 (long)ND_IFINFO(ifa->ifa_ifp)->retrans * hz / 1000);
1290 } else { 1290 } else {
1291 /* 1291 /*
@@ -1312,35 +1312,38 @@ nd6_dad_timer(struct ifaddr *ifa) @@ -1312,35 +1312,38 @@ nd6_dad_timer(struct ifaddr *ifa)
1312 /* 1312 /*
1313 * We are done with DAD. No NA came, no NS came. 1313 * We are done with DAD. No NA came, no NS came.
1314 * No duplicate address found. 1314 * No duplicate address found.
1315 */ 1315 */
1316 ia->ia6_flags &= ~IN6_IFF_TENTATIVE; 1316 ia->ia6_flags &= ~IN6_IFF_TENTATIVE;
1317 rt_newaddrmsg(RTM_NEWADDR, ifa, 0, NULL); 1317 rt_newaddrmsg(RTM_NEWADDR, ifa, 0, NULL);
1318 1318
1319 nd6log(LOG_DEBUG, 1319 nd6log(LOG_DEBUG,
1320 "%s: DAD complete for %s - no duplicates found\n", 1320 "%s: DAD complete for %s - no duplicates found\n",
1321 if_name(ifa->ifa_ifp), 1321 if_name(ifa->ifa_ifp),
1322 IN6_PRINT(ip6buf, &ia->ia_addr.sin6_addr)); 1322 IN6_PRINT(ip6buf, &ia->ia_addr.sin6_addr));
1323 1323
1324 TAILQ_REMOVE(&dadq, dp, dad_list); 1324 TAILQ_REMOVE(&dadq, dp, dad_list);
1325 free(dp, M_IP6NDP); 1325 need_free = true;
1326 dp = NULL; 
1327 ifafree(ifa); 
1328 } 1326 }
1329 } 1327 }
1330 
1331done: 1328done:
1332 mutex_exit(&nd6_dad_lock); 1329 mutex_exit(&nd6_dad_lock);
1333 1330
 1331 if (need_free) {
 1332 kmem_intr_free(dp, sizeof(*dp));
 1333 ifafree(ifa);
 1334 ifa = NULL;
 1335 }
 1336
1334 if (duplicate) 1337 if (duplicate)
1335 nd6_dad_duplicated(ifa); 1338 nd6_dad_duplicated(ifa);
1336 1339
1337#ifndef NET_MPSAFE 1340#ifndef NET_MPSAFE
1338 KERNEL_UNLOCK_ONE(NULL); 1341 KERNEL_UNLOCK_ONE(NULL);
1339 mutex_exit(softnet_lock); 1342 mutex_exit(softnet_lock);
1340#endif 1343#endif
1341} 1344}
1342 1345
1343static void 1346static void
1344nd6_dad_duplicated(struct ifaddr *ifa) 1347nd6_dad_duplicated(struct ifaddr *ifa)
1345{ 1348{
1346 struct in6_ifaddr *ia = (struct in6_ifaddr *)ifa; 1349 struct in6_ifaddr *ia = (struct in6_ifaddr *)ifa;
@@ -1403,28 +1406,27 @@ nd6_dad_duplicated(struct ifaddr *ifa) @@ -1403,28 +1406,27 @@ nd6_dad_duplicated(struct ifaddr *ifa)
1403 IN6_ARE_ADDR_EQUAL(&ia->ia_addr.sin6_addr, &in6)) { 1406 IN6_ARE_ADDR_EQUAL(&ia->ia_addr.sin6_addr, &in6)) {
1404 ND_IFINFO(ifp)->flags |= ND6_IFF_IFDISABLED; 1407 ND_IFINFO(ifp)->flags |= ND6_IFF_IFDISABLED;
1405 log(LOG_ERR, "%s: possible hardware address " 1408 log(LOG_ERR, "%s: possible hardware address "
1406 "duplication detected, disable IPv6\n", 1409 "duplication detected, disable IPv6\n",
1407 if_name(ifp)); 1410 if_name(ifp));
1408 } 1411 }
1409 break; 1412 break;
1410 } 1413 }
1411 } 1414 }
1412 1415
1413 TAILQ_REMOVE(&dadq, dp, dad_list); 1416 TAILQ_REMOVE(&dadq, dp, dad_list);
1414 mutex_exit(&nd6_dad_lock); 1417 mutex_exit(&nd6_dad_lock);
1415 1418
1416 free(dp, M_IP6NDP); 1419 kmem_intr_free(dp, sizeof(*dp));
1417 dp = NULL; 
1418 ifafree(ifa); 1420 ifafree(ifa);
1419} 1421}
1420 1422
1421static void 1423static void
1422nd6_dad_ns_output(struct dadq *dp, struct ifaddr *ifa) 1424nd6_dad_ns_output(struct dadq *dp, struct ifaddr *ifa)
1423{ 1425{
1424 struct in6_ifaddr *ia = (struct in6_ifaddr *)ifa; 1426 struct in6_ifaddr *ia = (struct in6_ifaddr *)ifa;
1425 struct ifnet *ifp = ifa->ifa_ifp; 1427 struct ifnet *ifp = ifa->ifa_ifp;
1426 1428
1427 dp->dad_ns_tcount++; 1429 dp->dad_ns_tcount++;
1428 if ((ifp->if_flags & IFF_UP) == 0) { 1430 if ((ifp->if_flags & IFF_UP) == 0) {
1429#if 0 1431#if 0
1430 printf("%s: interface down?\n", if_name(ifp)); 1432 printf("%s: interface down?\n", if_name(ifp));