Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. =================================================================== RCS file: /ftp/cvs/cvsroot/src/sys/netinet/ip_input.c,v rcsdiff: /ftp/cvs/cvsroot/src/sys/netinet/ip_input.c,v: warning: Unknown phrases like `commitid ...;' are present. retrieving revision 1.339 retrieving revision 1.344 diff -u -p -r1.339 -r1.344 --- src/sys/netinet/ip_input.c 2016/08/01 03:15:30 1.339 +++ src/sys/netinet/ip_input.c 2016/10/18 07:30:31 1.344 @@ -1,4 +1,4 @@ -/* $NetBSD: ip_input.c,v 1.339 2016/08/01 03:15:30 ozaki-r Exp $ */ +/* $NetBSD: ip_input.c,v 1.344 2016/10/18 07:30:31 ozaki-r Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. @@ -91,7 +91,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: ip_input.c,v 1.339 2016/08/01 03:15:30 ozaki-r Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ip_input.c,v 1.344 2016/10/18 07:30:31 ozaki-r Exp $"); #ifdef _KERNEL_OPT #include "opt_inet.h" @@ -101,6 +101,7 @@ __KERNEL_RCSID(0, "$NetBSD: ip_input.c,v #include "opt_mrouting.h" #include "opt_mbuftrace.h" #include "opt_inet_csum.h" +#include "opt_net_mpsafe.h" #endif #include "arp.h" @@ -225,7 +226,7 @@ pfil_head_t * inet_pfil_hook __read_mo ipid_state_t * ip_ids __read_mostly; percpu_t * ipstat_percpu __read_mostly; -static struct route ipforward_rt __cacheline_aligned; +static percpu_t *ipforward_rt_percpu __cacheline_aligned; uint16_t ip_id; @@ -294,9 +295,13 @@ static struct in_ifaddr *ip_match_our_ad static struct in_ifaddr *ip_match_our_address_broadcast(struct ifnet *, struct ip *); -/* XXX: Not yet enabled. */ +#ifdef NET_MPSAFE +#define SOFTNET_LOCK() mutex_enter(softnet_lock) +#define SOFTNET_UNLOCK() mutex_exit(softnet_lock) +#else #define SOFTNET_LOCK() KASSERT(mutex_owned(softnet_lock)) #define SOFTNET_UNLOCK() KASSERT(mutex_owned(softnet_lock)) +#endif /* * IP initialization: fill in IP protocol switch table. @@ -345,6 +350,10 @@ ip_init(void) #endif /* MBUFTRACE */ ipstat_percpu = percpu_alloc(sizeof(uint64_t) * IP_NSTATS); + + ipforward_rt_percpu = percpu_alloc(sizeof(struct route)); + if (ipforward_rt_percpu == NULL) + panic("failed to allocate ipforward_rt_percpu"); } static struct in_ifaddr * @@ -378,7 +387,8 @@ ip_match_our_address(struct ifnet *ifp, continue; if (checkif && ia->ia_ifp != ifp) continue; - if ((ia->ia_ifp->if_flags & IFF_UP) != 0) + if ((ia->ia_ifp->if_flags & IFF_UP) != 0 && + (ia->ia4_flags & IN_IFF_DETACHED) == 0) break; else (*downmatch)++; @@ -398,7 +408,7 @@ ip_match_our_address_broadcast(struct if if (ifa->ifa_addr->sa_family != AF_INET) continue; ia = ifatoia(ifa); - if (ia->ia4_flags & IN_IFF_NOTREADY) + if (ia->ia4_flags & (IN_IFF_NOTREADY | IN_IFF_DETACHED)) continue; if (in_hosteq(ip->ip_dst, ia->ia_broadaddr.sin_addr) || in_hosteq(ip->ip_dst, ia->ia_netbroadcast) || @@ -432,11 +442,15 @@ ipintr(void *arg __unused) KASSERT(cpu_softintr_p()); +#ifndef NET_MPSAFE mutex_enter(softnet_lock); +#endif while ((m = pktq_dequeue(ip_pktq)) != NULL) { ip_input(m); } +#ifndef NET_MPSAFE mutex_exit(softnet_lock); +#endif } /* @@ -609,10 +623,9 @@ ip_input(struct mbuf *m) struct in_addr odst = ip->ip_dst; bool freed; - SOFTNET_LOCK(); freed = pfil_run_hooks(inet_pfil_hook, &m, ifp, PFIL_IN) != 0; - SOFTNET_UNLOCK(); if (freed || m == NULL) { + m = NULL; goto out; } ip = mtod(m, struct ip *); @@ -642,6 +655,7 @@ ip_input(struct mbuf *m) if ((*altq_input)(m, AF_INET) == 0) { /* Packet dropped by traffic conditioner. */ SOFTNET_UNLOCK(); + m = NULL; goto out; } SOFTNET_UNLOCK(); @@ -655,8 +669,10 @@ ip_input(struct mbuf *m) * to be sent and the original packet to be freed). */ ip_nhops = 0; /* for source routed packets */ - if (hlen > sizeof (struct ip) && ip_dooptions(m)) + if (hlen > sizeof (struct ip) && ip_dooptions(m)) { + m = NULL; goto out; + } /* * Check our list of addresses, to see if the packet is for us. @@ -824,7 +840,7 @@ ours: * is expensive, so explore ia here again. */ s = pserialize_read_enter(); - _ia = in_get_ia(ip->ip_dst.s_addr); + _ia = in_get_ia(ip->ip_dst); _ia->ia_ifa.ifa_data.ifad_inbytes += ntohs(ip->ip_len); pserialize_read_exit(s); } @@ -1163,11 +1179,14 @@ ip_rtaddr(struct in_addr dst) struct sockaddr dst; struct sockaddr_in dst4; } u; + struct route *ro; sockaddr_in_init(&u.dst4, &dst, 0); SOFTNET_LOCK(); - rt = rtcache_lookup(&ipforward_rt, &u.dst); + ro = percpu_getref(ipforward_rt_percpu); + rt = rtcache_lookup(ro, &u.dst); + percpu_putref(ipforward_rt_percpu); SOFTNET_UNLOCK(); if (rt == NULL) return NULL; @@ -1300,6 +1319,7 @@ ip_forward(struct mbuf *m, int srcrt, st struct sockaddr_in dst4; } u; uint64_t *ips; + struct route *ro; KASSERTMSG(cpu_softintr_p(), "ip_forward: not in the software " "interrupt handler; synchronization assumptions violated"); @@ -1321,19 +1341,17 @@ ip_forward(struct mbuf *m, int srcrt, st return; } - SOFTNET_LOCK(); - if (ip->ip_ttl <= IPTTLDEC) { icmp_error(m, ICMP_TIMXCEED, ICMP_TIMXCEED_INTRANS, dest, 0); - SOFTNET_UNLOCK(); return; } sockaddr_in_init(&u.dst4, &ip->ip_dst, 0); - if ((rt = rtcache_lookup(&ipforward_rt, &u.dst)) == NULL) { + ro = percpu_getref(ipforward_rt_percpu); + if ((rt = rtcache_lookup(ro, &u.dst)) == NULL) { + percpu_putref(ipforward_rt_percpu); icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_NET, dest, 0); - SOFTNET_UNLOCK(); return; } @@ -1376,7 +1394,7 @@ ip_forward(struct mbuf *m, int srcrt, st } } - error = ip_output(m, NULL, &ipforward_rt, + error = ip_output(m, NULL, ro, (IP_FORWARDING | (ip_directedbcast ? IP_ALLOWBROADCAST : 0)), NULL, NULL); @@ -1398,18 +1416,18 @@ ip_forward(struct mbuf *m, int srcrt, st if (mcopy) { #ifdef GATEWAY if (mcopy->m_flags & M_CANFASTFWD) - ipflow_create(&ipforward_rt, mcopy); + ipflow_create(ro, mcopy); #endif m_freem(mcopy); } - SOFTNET_UNLOCK(); + percpu_putref(ipforward_rt_percpu); return; redirect: error: if (mcopy == NULL) { - SOFTNET_UNLOCK(); + percpu_putref(ipforward_rt_percpu); return; } @@ -1432,7 +1450,7 @@ error: type = ICMP_UNREACH; code = ICMP_UNREACH_NEEDFRAG; - if ((rt = rtcache_validate(&ipforward_rt)) != NULL) + if ((rt = rtcache_validate(ro)) != NULL) destmtu = rt->rt_ifp->if_mtu; #ifdef IPSEC if (ipsec_used) @@ -1450,11 +1468,11 @@ error: */ if (mcopy) m_freem(mcopy); - SOFTNET_UNLOCK(); + percpu_putref(ipforward_rt_percpu); return; } icmp_error(mcopy, type, code, dest, destmtu); - SOFTNET_UNLOCK(); + percpu_putref(ipforward_rt_percpu); } void