Tue Oct 13 09:33:35 2015 UTC ()
Simplify la handling in arpresolve() by asking arplookup() not to create
a la. If a la is needed arpresolve() will then create it or mark the
current la as writable.


(roy)
diff -r1.184 -r1.185 src/sys/netinet/if_arp.c

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

--- src/sys/netinet/if_arp.c 2015/10/08 08:17:37 1.184
+++ src/sys/netinet/if_arp.c 2015/10/13 09:33:35 1.185
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: if_arp.c,v 1.184 2015/10/08 08:17:37 roy Exp $ */ 1/* $NetBSD: if_arp.c,v 1.185 2015/10/13 09:33:35 roy 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,27 +58,27 @@ @@ -58,27 +58,27 @@
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.184 2015/10/08 08:17:37 roy Exp $"); 71__KERNEL_RCSID(0, "$NetBSD: if_arp.c,v 1.185 2015/10/13 09:33:35 roy 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#endif 76#endif
77 77
78#ifdef INET 78#ifdef INET
79 79
80#include "bridge.h" 80#include "bridge.h"
81 81
82#include <sys/param.h> 82#include <sys/param.h>
83#include <sys/systm.h> 83#include <sys/systm.h>
84#include <sys/callout.h> 84#include <sys/callout.h>
@@ -781,223 +781,215 @@ arprequest(struct ifnet *ifp, @@ -781,223 +781,215 @@ arprequest(struct ifnet *ifp,
781 * set one up and broadcast a request for the IP address. 781 * set one up and broadcast a request for the IP address.
782 * Hold onto this mbuf and resend it once the address 782 * Hold onto this mbuf and resend it once the address
783 * is finally resolved. A return value of 1 indicates 783 * is finally resolved. A return value of 1 indicates
784 * that desten has been filled in and the packet should be sent 784 * that desten has been filled in and the packet should be sent
785 * normally; a 0 return indicates that the packet has been 785 * normally; a 0 return indicates that the packet has been
786 * taken over here, either now or for later transmission. 786 * taken over here, either now or for later transmission.
787 */ 787 */
788int 788int
789arpresolve(struct ifnet *ifp, struct rtentry *rt, struct mbuf *m, 789arpresolve(struct ifnet *ifp, struct rtentry *rt, struct mbuf *m,
790 const struct sockaddr *dst, u_char *desten) 790 const struct sockaddr *dst, u_char *desten)
791{ 791{
792 struct llentry *la; 792 struct llentry *la;
793 const struct sockaddr_dl *sdl; 793 const struct sockaddr_dl *sdl;
794 int renew; 794 const char *create_lookup;
795 int flags = 0; 795 bool renew;
796 int error; 796 int error;
797 797
798 KASSERT(m != NULL); 798 KASSERT(m != NULL);
799 799
800 la = arplookup(ifp, m, &satocsin(dst)->sin_addr, 1, 0, 0, rt); 800 la = arplookup(ifp, m, &satocsin(dst)->sin_addr, 0, 0, 0, rt);
801 if (la != NULL) 801 if (la == NULL || la->la_rt == NULL)
802 rt = la->la_rt; 802 goto notfound;
803 803
804 if (la == NULL || rt == NULL) { 804 rt = la->la_rt;
805 ARP_STATINC(ARP_STAT_ALLOCFAIL); 
806 log(LOG_DEBUG, 
807 "arpresolve: can't allocate llinfo on %s for %s\n", 
808 ifp->if_xname, in_fmtaddr(satocsin(dst)->sin_addr)); 
809 m_freem(m); 
810 if (la != NULL) 
811 LLE_RUNLOCK(la); 
812 return 0; 
813 } 
814 sdl = satocsdl(rt->rt_gateway); 805 sdl = satocsdl(rt->rt_gateway);
815 /* 806 /*
816 * Check the address family and length is valid, the address 807 * Check the address family and length is valid, the address
817 * is resolved; otherwise, try to resolve. 808 * is resolved; otherwise, try to resolve.
818 */ 809 */
819 if ((rt->rt_expire == 0 || rt->rt_expire > time_uptime) && 810 if ((rt->rt_expire == 0 || rt->rt_expire > time_uptime) &&
820 sdl->sdl_family == AF_LINK && sdl->sdl_alen != 0) { 811 sdl->sdl_family == AF_LINK && sdl->sdl_alen != 0) {
821 memcpy(desten, CLLADDR(sdl), 812 memcpy(desten, CLLADDR(sdl),
822 min(sdl->sdl_alen, ifp->if_addrlen)); 813 min(sdl->sdl_alen, ifp->if_addrlen));
823 rt->rt_pksent = time_uptime; /* Time for last pkt sent */ 814 rt->rt_pksent = time_uptime; /* Time for last pkt sent */
824 LLE_RUNLOCK(la); 815 LLE_RUNLOCK(la);
825 return 1; 816 return 1;
826 } 817 }
827 818
828 /* 819 /*
829 * Re-send the ARP request when appropriate. 820 * Re-send the ARP request when appropriate.
830 */ 821 */
831#ifdef DIAGNOSTIC 822#ifdef DIAGNOSTIC
832 if (rt->rt_expire == 0) { 823 if (rt->rt_expire == 0) {
833 /* This should never happen. (Should it? -gwr) */ 824 /* This should never happen. (Should it? -gwr) */
834 printf("arpresolve: unresolved and rt_expire == 0\n"); 825 printf("arpresolve: unresolved and rt_expire == 0\n");
835 /* Set expiration time to now (expired). */ 826 /* Set expiration time to now (expired). */
836 rt->rt_expire = time_uptime; 827 rt->rt_expire = time_uptime;
837 } 828 }
838#endif 829#endif
839 830
840retry: 831notfound:
841 if (la == NULL) { 832 if (la == NULL) {
842 IF_AFDATA_RLOCK(ifp); 
843 la = lla_lookup(LLTABLE(ifp), flags, dst); 
844 IF_AFDATA_RUNLOCK(ifp); 
845 } 
846 
847#ifdef IFF_STATICARP /* FreeBSD */ 833#ifdef IFF_STATICARP /* FreeBSD */
848#define _IFF_NOARP (IFF_NOARP | IFF_STATICARP) 834#define _IFF_NOARP (IFF_NOARP | IFF_STATICARP)
849#else 835#else
850#define _IFF_NOARP IFF_NOARP 836#define _IFF_NOARP IFF_NOARP
851#endif 837#endif
852 if ((la == NULL) && ((flags & LLE_EXCLUSIVE) == 0) 838 if (ifp->if_flags & _IFF_NOARP) {
853 && ((ifp->if_flags & _IFF_NOARP) == 0)) 839 m_freem(m);
854 { 840 return 0;
855 flags |= LLE_EXCLUSIVE; 841 }
 842#undef _IFF_NOARP
 843 create_lookup = "create";
856 IF_AFDATA_WLOCK(ifp); 844 IF_AFDATA_WLOCK(ifp);
857 la = lla_create(LLTABLE(ifp), flags, dst); 845 la = lla_create(LLTABLE(ifp), LLE_EXCLUSIVE, dst);
858 IF_AFDATA_WUNLOCK(ifp); 846 IF_AFDATA_WUNLOCK(ifp);
859 847 if (la == NULL)
860 if (la == NULL) { 848 ARP_STATINC(ARP_STAT_ALLOCFAIL);
861 log(LOG_DEBUG, 849 } else if (LLE_TRY_UPGRADE(la) == 0) {
862 "%s: failed to create llentry for %s on %s\n", 850 create_lookup = "lookup";
863 __func__, inet_ntoa(satocsin(dst)->sin_addr), 851 LLE_RUNLOCK(la);
864 ifp->if_xname); 852 IF_AFDATA_RLOCK(ifp);
865 } 853 la = lla_lookup(LLTABLE(ifp), LLE_EXCLUSIVE, dst);
 854 IF_AFDATA_RUNLOCK(ifp);
866 } 855 }
867#undef _IFF_NOARP 
868 856
869 if (la == NULL) { 857 if (la == NULL) {
 858 log(LOG_DEBUG,
 859 "%s: failed to %s llentry for %s on %s\n",
 860 __func__, create_lookup, inet_ntoa(satocsin(dst)->sin_addr),
 861 ifp->if_xname);
870 m_freem(m); 862 m_freem(m);
871 return 0; 863 return 0;
872 } 864 }
873 865
 866 /* Just in case */
 867 if (la->la_rt == NULL) {
 868 log(LOG_DEBUG,
 869 "%s: valid llentry has no rtentry for %s on %s\n",
 870 __func__, inet_ntoa(satocsin(dst)->sin_addr),
 871 ifp->if_xname);
 872 m_freem(m);
 873 return 0;
 874 }
 875 rt = la->la_rt;
 876
874 if ((la->la_flags & LLE_VALID) && 877 if ((la->la_flags & LLE_VALID) &&
875 ((la->la_flags & LLE_STATIC) || la->la_expire > time_uptime)) { 878 ((la->la_flags & LLE_STATIC) || la->la_expire > time_uptime))
 879 {
 880 sdl = satocsdl(rt->rt_gateway);
876 memcpy(desten, CLLADDR(sdl), 881 memcpy(desten, CLLADDR(sdl),
877 min(sdl->sdl_alen, ifp->if_addrlen)); 882 min(sdl->sdl_alen, ifp->if_addrlen));
878 renew = 0; 883 renew = false;
879 /* 884 /*
880 * If entry has an expiry time and it is approaching, 885 * If entry has an expiry time and it is approaching,
881 * see if we need to send an ARP request within this 886 * see if we need to send an ARP request within this
882 * arpt_down interval. 887 * arpt_down interval.
883 */ 888 */
884 if (!(la->la_flags & LLE_STATIC) && 889 if (!(la->la_flags & LLE_STATIC) &&
885 time_uptime + la->la_preempt > la->la_expire) { 890 time_uptime + la->la_preempt > la->la_expire)
886 renew = 1; 891 {
 892 renew = true;
887 la->la_preempt--; 893 la->la_preempt--;
888 } 894 }
889 895
890 if (flags & LLE_EXCLUSIVE) 896 LLE_WUNLOCK(la);
891 LLE_WUNLOCK(la); 
892 else 
893 LLE_RUNLOCK(la); 
894 897
895 if (renew == 1) { 898 if (renew) {
896 const u_int8_t *enaddr = 899 const u_int8_t *enaddr =
897#if NCARP > 0 900#if NCARP > 0
898 (rt->rt_ifp->if_type == IFT_CARP) ? 901 (rt->rt_ifp->if_type == IFT_CARP) ?
899 CLLADDR(rt->rt_ifp->if_sadl): 902 CLLADDR(rt->rt_ifp->if_sadl):
900#endif 903#endif
901 CLLADDR(ifp->if_sadl); 904 CLLADDR(ifp->if_sadl);
902 arprequest(ifp, &satocsin(rt->rt_ifa->ifa_addr)->sin_addr, 905 arprequest(ifp,
 906 &satocsin(rt->rt_ifa->ifa_addr)->sin_addr,
903 &satocsin(dst)->sin_addr, enaddr); 907 &satocsin(dst)->sin_addr, enaddr);
904 } 908 }
905 909
906 return 1; 910 return 1;
907 } 911 }
908 912
909 if (la->la_flags & LLE_STATIC) { /* should not happen! */ 913 if (la->la_flags & LLE_STATIC) { /* should not happen! */
910 log(LOG_DEBUG, "arpresolve: ouch, empty static llinfo for %s\n", 914 log(LOG_DEBUG, "arpresolve: ouch, empty static llinfo for %s\n",
911 inet_ntoa(satocsin(dst)->sin_addr)); 915 inet_ntoa(satocsin(dst)->sin_addr));
912 m_freem(m); 916 m_freem(m);
913 error = EINVAL; 917 error = EINVAL;
914 goto done; 918 goto done;
915 } 919 }
916 920
917 renew = (la->la_asked == 0 || la->la_expire != time_uptime); 921 renew = (la->la_asked == 0 || la->la_expire != time_uptime);
918 if (renew && (flags & LLE_EXCLUSIVE) == 0) { 
919 flags |= LLE_EXCLUSIVE; 
920 LLE_RUNLOCK(la); 
921 la = NULL; 
922 goto retry; 
923 } 
924 922
925 /* 923 /*
926 * There is an arptab entry, but no ethernet address 924 * There is an arptab entry, but no ethernet address
927 * response yet. Add the mbuf to the list, dropping 925 * response yet. Add the mbuf to the list, dropping
928 * the oldest packet if we have exceeded the system 926 * the oldest packet if we have exceeded the system
929 * setting. 927 * setting.
930 */ 928 */
931 LLE_WLOCK_ASSERT(la); 929 LLE_WLOCK_ASSERT(la);
932 if (la->la_numheld >= arp_maxhold) { 930 if (la->la_numheld >= arp_maxhold) {
933 if (la->la_hold != NULL) { 931 if (la->la_hold != NULL) {
934 struct mbuf *next = la->la_hold->m_nextpkt; 932 struct mbuf *next = la->la_hold->m_nextpkt;
935 m_freem(la->la_hold); 933 m_freem(la->la_hold);
936 la->la_hold = next; 934 la->la_hold = next;
937 la->la_numheld--; 935 la->la_numheld--;
938 ARP_STATINC(ARP_STAT_DFRDROPPED); 936 ARP_STATINC(ARP_STAT_DFRDROPPED);
939 } 937 }
940 } 938 }
941 if (la->la_hold != NULL) { 939 if (la->la_hold != NULL) {
942 struct mbuf *curr = la->la_hold; 940 struct mbuf *curr = la->la_hold;
943 while (curr->m_nextpkt != NULL) 941 while (curr->m_nextpkt != NULL)
944 curr = curr->m_nextpkt; 942 curr = curr->m_nextpkt;
945 curr->m_nextpkt = m; 943 curr->m_nextpkt = m;
946 } else 944 } else
947 la->la_hold = m; 945 la->la_hold = m;
948 la->la_numheld++; 946 la->la_numheld++;
949 if (renew == 0 && (flags & LLE_EXCLUSIVE)) { 947 if (!renew)
950 flags &= ~LLE_EXCLUSIVE; 
951 LLE_DOWNGRADE(la); 948 LLE_DOWNGRADE(la);
952 } 
953 949
954 /* 950 /*
955 * Return EWOULDBLOCK if we have tried less than arp_maxtries. It 951 * Return EWOULDBLOCK if we have tried less than arp_maxtries. It
956 * will be masked by ether_output(). Return EHOSTDOWN/EHOSTUNREACH 952 * will be masked by ether_output(). Return EHOSTDOWN/EHOSTUNREACH
957 * if we have already sent arp_maxtries ARP requests. Retransmit the 953 * if we have already sent arp_maxtries ARP requests. Retransmit the
958 * ARP request, but not faster than one request per second. 954 * ARP request, but not faster than one request per second.
959 */ 955 */
960 if (la->la_asked < arp_maxtries) 956 if (la->la_asked < arp_maxtries)
961 error = EWOULDBLOCK; /* First request. */ 957 error = EWOULDBLOCK; /* First request. */
962 else 958 else
963 error = (rt->rt_flags & RTF_GATEWAY) ? 959 error = (rt->rt_flags & RTF_GATEWAY) ?
964 EHOSTUNREACH : EHOSTDOWN; 960 EHOSTUNREACH : EHOSTDOWN;
965 961
966 if (renew) { 962 if (renew) {
967 const u_int8_t *enaddr = 963 const u_int8_t *enaddr =
968#if NCARP > 0 964#if NCARP > 0
969 (rt->rt_ifp->if_type == IFT_CARP) ? 965 (rt->rt_ifp->if_type == IFT_CARP) ?
970 CLLADDR(rt->rt_ifp->if_sadl): 966 CLLADDR(rt->rt_ifp->if_sadl):
971#endif 967#endif
972 CLLADDR(ifp->if_sadl); 968 CLLADDR(ifp->if_sadl);
973 LLE_ADDREF(la); 969 LLE_ADDREF(la);
974 la->la_expire = time_uptime; 970 la->la_expire = time_uptime;
975 callout_reset(&la->la_timer, hz * arpt_down, 971 callout_reset(&la->la_timer, hz * arpt_down,
976 arptimer, la); 972 arptimer, la);
977 la->la_asked++; 973 la->la_asked++;
978 if (flags & LLE_EXCLUSIVE) 974 LLE_WUNLOCK(la);
979 LLE_WUNLOCK(la); 975
980 else 
981 LLE_RUNLOCK(la); 
982 arprequest(ifp, &satocsin(rt->rt_ifa->ifa_addr)->sin_addr, 976 arprequest(ifp, &satocsin(rt->rt_ifa->ifa_addr)->sin_addr,
983 &satocsin(dst)->sin_addr, enaddr); 977 &satocsin(dst)->sin_addr, enaddr);
984 return error == 0; 978 return error == 0;
985 } 979 }
986done: 980done:
987 if (flags & LLE_EXCLUSIVE) 981 LLE_RUNLOCK(la);
988 LLE_WUNLOCK(la); 982
989 else 
990 LLE_RUNLOCK(la); 
991 return error == 0; 983 return error == 0;
992} 984}
993 985
994/* 986/*
995 * Common length and type checks are done here, 987 * Common length and type checks are done here,
996 * then the protocol-specific routine is called. 988 * then the protocol-specific routine is called.
997 */ 989 */
998void 990void
999arpintr(void) 991arpintr(void)
1000{ 992{
1001 struct mbuf *m; 993 struct mbuf *m;
1002 struct arphdr *ar; 994 struct arphdr *ar;
1003 int s; 995 int s;