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/net/if_ethersubr.c,v rcsdiff: /ftp/cvs/cvsroot/src/sys/net/if_ethersubr.c,v: warning: Unknown phrases like `commitid ...;' are present. retrieving revision 1.196.2.2 retrieving revision 1.197 diff -u -p -r1.196.2.2 -r1.197 --- src/sys/net/if_ethersubr.c 2014/08/10 06:56:15 1.196.2.2 +++ src/sys/net/if_ethersubr.c 2014/05/13 19:36:16 1.197 @@ -1,4 +1,4 @@ -/* $NetBSD: if_ethersubr.c,v 1.196.2.2 2014/08/10 06:56:15 tls Exp $ */ +/* $NetBSD: if_ethersubr.c,v 1.197 2014/05/13 19:36:16 bouyer Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. @@ -61,7 +61,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: if_ethersubr.c,v 1.196.2.2 2014/08/10 06:56:15 tls Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_ethersubr.c,v 1.197 2014/05/13 19:36:16 bouyer Exp $"); #include "opt_inet.h" #include "opt_atalk.h" @@ -78,7 +78,6 @@ __KERNEL_RCSID(0, "$NetBSD: if_ethersubr #include #include -#include #include #include #include @@ -92,7 +91,6 @@ __KERNEL_RCSID(0, "$NetBSD: if_ethersubr #include #include #include -#include #include #include @@ -176,7 +174,6 @@ extern u_char aarp_org_code[3]; static struct timeval bigpktppslim_last; static int bigpktppslim = 2; /* XXX */ static int bigpktpps_count; -static kmutex_t bigpktpps_lock __cacheline_aligned; const uint8_t etherbroadcastaddr[ETHER_ADDR_LEN] = @@ -578,13 +575,10 @@ void ether_input(struct ifnet *ifp, struct mbuf *m) { struct ethercom *ec = (struct ethercom *) ifp; - pktqueue_t *pktq = NULL; - struct ifqueue *inq = NULL; + struct ifqueue *inq; uint16_t etype; struct ether_header *eh; size_t ehlen; - static int earlypkts; - int isr = 0; #if defined (LLC) || defined(NETATALK) struct llc *l; #endif @@ -601,23 +595,16 @@ ether_input(struct ifnet *ifp, struct mb etype = ntohs(eh->ether_type); ehlen = sizeof(*eh); - if(__predict_false(earlypkts < 100 || !rnd_initial_entropy)) { - rnd_add_data(NULL, eh, ehlen, 0); - earlypkts++; - } - /* * Determine if the packet is within its size limits. */ if (etype != ETHERTYPE_MPLS && m->m_pkthdr.len > ETHER_MAX_FRAME(ifp, etype, m->m_flags & M_HASFCS)) { - mutex_enter(&bigpktpps_lock); if (ppsratecheck(&bigpktppslim_last, &bigpktpps_count, bigpktppslim)) { printf("%s: discarding oversize frame (len=%d)\n", ifp->if_xname, m->m_pkthdr.len); } - mutex_exit(&bigpktpps_lock); m_freem(m); return; } @@ -650,23 +637,49 @@ ether_input(struct ifnet *ifp, struct mb ifp->if_ibytes += m->m_pkthdr.len; -#if NCARP > 0 - if (__predict_false(ifp->if_carp && ifp->if_type != IFT_CARP)) { - /* - * clear M_PROMISC, in case the packets comes from a - * vlan - */ +#if NBRIDGE > 0 + /* + * Tap the packet off here for a bridge. bridge_input() + * will return NULL if it has consumed the packet, otherwise + * it gets processed as normal. Note that bridge_input() + * will always return the original packet if we need to + * process it locally. + */ + if (ifp->if_bridge) { + /* clear M_PROMISC, in case the packets comes from a vlan */ m->m_flags &= ~M_PROMISC; - if (carp_input(m, (uint8_t *)&eh->ether_shost, - (uint8_t *)&eh->ether_dhost, eh->ether_type) == 0) + m = bridge_input(ifp, m); + if (m == NULL) return; - } + + /* + * Bridge has determined that the packet is for us. + * Update our interface pointer -- we may have had + * to "bridge" the packet locally. + */ + ifp = m->m_pkthdr.rcvif; + } else +#endif /* NBRIDGE > 0 */ + { + +#if NCARP > 0 + if (__predict_false(ifp->if_carp && ifp->if_type != IFT_CARP)) { + /* + * clear M_PROMISC, in case the packets comes from a + * vlan + */ + m->m_flags &= ~M_PROMISC; + if (carp_input(m, (uint8_t *)&eh->ether_shost, + (uint8_t *)&eh->ether_dhost, eh->ether_type) == 0) + return; + } #endif /* NCARP > 0 */ - if ((m->m_flags & (M_BCAST|M_MCAST|M_PROMISC)) == 0 && - (ifp->if_flags & IFF_PROMISC) != 0 && - memcmp(CLLADDR(ifp->if_sadl), eh->ether_dhost, - ETHER_ADDR_LEN) != 0) { - m->m_flags |= M_PROMISC; + if ((m->m_flags & (M_BCAST|M_MCAST|M_PROMISC)) == 0 && + (ifp->if_flags & IFF_PROMISC) != 0 && + memcmp(CLLADDR(ifp->if_sadl), eh->ether_dhost, + ETHER_ADDR_LEN) != 0) { + m->m_flags |= M_PROMISC; + } } if ((m->m_flags & M_PROMISC) == 0) { @@ -761,10 +774,9 @@ ether_input(struct ifnet *ifp, struct mb if (IF_QFULL(inq)) { IF_DROP(inq); m_freem(m); - } else { + } else IF_ENQUEUE(inq, m); - softint_schedule(pppoe_softintr); - } + softint_schedule(pppoe_softintr); return; #endif /* NPPPOE > 0 */ case ETHERTYPE_SLOWPROTOCOLS: { @@ -827,11 +839,12 @@ ether_input(struct ifnet *ifp, struct mb if (ipflow_fastforward(m)) return; #endif - pktq = ip_pktq; + schednetisr(NETISR_IP); + inq = &ipintrq; break; case ETHERTYPE_ARP: - isr = NETISR_ARP; + schednetisr(NETISR_ARP); inq = &arpintrq; break; @@ -849,18 +862,19 @@ ether_input(struct ifnet *ifp, struct mb if (ip6flow_fastforward(&m)) return; #endif - pktq = ip6_pktq; + schednetisr(NETISR_IPV6); + inq = &ip6intrq; break; #endif #ifdef IPX case ETHERTYPE_IPX: - isr = NETISR_IPX; + schednetisr(NETISR_IPX); inq = &ipxintrq; break; #endif #ifdef NETATALK case ETHERTYPE_ATALK: - isr = NETISR_ATALK; + schednetisr(NETISR_ATALK); inq = &atintrq1; break; case ETHERTYPE_AARP: @@ -870,7 +884,7 @@ ether_input(struct ifnet *ifp, struct mb #endif /* NETATALK */ #ifdef MPLS case ETHERTYPE_MPLS: - isr = NETISR_MPLS; + schednetisr(NETISR_MPLS); inq = &mplsintrq; break; #endif @@ -897,7 +911,7 @@ ether_input(struct ifnet *ifp, struct mb inq = &atintrq2; m_adj(m, sizeof(struct ether_header) + sizeof(struct llc)); - isr = NETISR_ATALK; + schednetisr(NETISR_ATALK); break; } @@ -928,26 +942,11 @@ ether_input(struct ifnet *ifp, struct mb #endif /* ISO || LLC || NETATALK*/ } - if (__predict_true(pktq)) { - const uint32_t h = pktq_rps_hash(m); - if (__predict_false(!pktq_enqueue(pktq, m, h))) { - m_freem(m); - } - return; - } - - if (__predict_false(!inq)) { - /* Should not happen. */ - m_freem(m); - return; - } if (IF_QFULL(inq)) { IF_DROP(inq); m_freem(m); - } else { + } else IF_ENQUEUE(inq, m); - schednetisr(isr); - } } /* @@ -1475,76 +1474,3 @@ ether_ioctl(struct ifnet *ifp, u_long cm } return 0; } - -static int -ether_multicast_sysctl(SYSCTLFN_ARGS) -{ - struct ether_multi *enm; - struct ether_multi_sysctl addr; - struct ifnet *ifp; - struct ethercom *ec; - int error; - size_t written; - - if (namelen != 1) - return EINVAL; - - ifp = if_byindex(name[0]); - if (ifp == NULL) - return ENODEV; - if (ifp->if_type != IFT_ETHER) { - *oldlenp = 0; - return 0; - } - ec = (struct ethercom *)ifp; - - if (oldp == NULL) { - *oldlenp = ec->ec_multicnt * sizeof(addr); - return 0; - } - - memset(&addr, 0, sizeof(addr)); - error = 0; - written = 0; - - LIST_FOREACH(enm, &ec->ec_multiaddrs, enm_list) { - if (written + sizeof(addr) > *oldlenp) - break; - addr.enm_refcount = enm->enm_refcount; - memcpy(addr.enm_addrlo, enm->enm_addrlo, ETHER_ADDR_LEN); - memcpy(addr.enm_addrhi, enm->enm_addrhi, ETHER_ADDR_LEN); - error = sysctl_copyout(l, &addr, oldp, sizeof(addr)); - if (error) - break; - written += sizeof(addr); - oldp = (char *)oldp + sizeof(addr); - } - - *oldlenp = written; - return error; -} - -SYSCTL_SETUP(sysctl_net_ether_setup, "sysctl net.ether subtree setup") -{ - const struct sysctlnode *rnode = NULL; - - sysctl_createv(clog, 0, NULL, &rnode, - CTLFLAG_PERMANENT, - CTLTYPE_NODE, "ether", - SYSCTL_DESCR("Ethernet-specific information"), - NULL, 0, NULL, 0, - CTL_NET, CTL_CREATE, CTL_EOL); - - sysctl_createv(clog, 0, &rnode, NULL, - CTLFLAG_PERMANENT, - CTLTYPE_NODE, "multicast", - SYSCTL_DESCR("multicast addresses"), - ether_multicast_sysctl, 0, NULL, 0, - CTL_CREATE, CTL_EOL); -} - -void -etherinit(void) -{ - mutex_init(&bigpktpps_lock, MUTEX_DEFAULT, IPL_NET); -}