--- aoenet.c.orig 2006-05-25 16:10:11 UTC +++ aoenet.c @@ -52,15 +52,26 @@ #include +#ifdef VIMAGE +#include +#define _aoenet_ifnet V_ifnet +#else +#define _aoenet_ifnet ifnet +#endif + /* * FORCE_NETWORK_HOOK is defined to support kernels that have not been patched * to recognize AoE packets. */ + #ifdef FORCE_NETWORK_HOOK static const u_char etherbroadcastaddr[ETHER_ADDR_LEN] = - { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; -static void (*old_ether_input)(struct ifnet *, struct mbuf *) = NULL; + { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; +typedef void (*ether_input_t)(struct ifnet *, struct mbuf *); +static ether_input_t old_ether_inputs[128]; // TODO: What happens if V_if_indexlim>128 ? +//static int ether_inputs_n = 0; #endif + extern boolean_t aoe_exiting; struct ifqueue aoeintrq; @@ -77,11 +88,14 @@ #define NECODES (sizeof(aoe_errlist) / sizeof(char *) - 1) #if (__FreeBSD_version < 600000) #define IFPADDR(ifp) (((struct arpcom *) (ifp))->ac_enaddr) -#else +#elif (__FreeBSD_version < 700000) #define IFPADDR(ifp) IFP2ENADDR(ifp) +#else +#include +#define IFPADDR(ifp) IF_LLADDR(ifp) #endif + #define IFLISTSZ 1024 - static char aoe_iflist[IFLISTSZ]; static int sysctl_aoe_iflist(SYSCTL_HANDLER_ARGS); @@ -160,7 +174,11 @@ register char *p, *q; register int len; +#if __FreeBSD_version >= 1100030 + switch (ifp->if_type) { +#else switch (ifp->if_data.ifi_type) { +#endif default: return (FALSE); case IFT_ETHER: @@ -190,19 +208,35 @@ /* * a dummy "free" function for mbuf ext buffer */ +#if __FreeBSD_version >= 1000050 +#if __FreeBSD_version >= 1100028 +static void +#else +static int +#endif +nilfn(struct mbuf *m, void *a, void *b) +{ +#if __FreeBSD_version < 1100028 + return EXT_FREE_OK; +#endif +} +#else static void nilfn(void *a, void *b) { } +#endif /* Create a mbuf chain and point to our data section(s). */ static struct mbuf * frame_mbufinit(struct frame *f) { - struct mbuf *m; + struct mbuf *m; - if ((m = m_gethdr(M_DONTWAIT, MT_DATA)) == NULL) + if ((m = m_gethdr(M_NOWAIT, MT_DATA)) == NULL) { + IPRINTK("m_gethdr failed\n"); return (NULL); + } m->m_len = AOEHDRSZ; m->m_pkthdr.len = f->f_mlen; MH_ALIGN(m, AOEHDRSZ); @@ -210,25 +244,33 @@ m->m_pkthdr.rcvif = NULL; m->m_next = NULL; - if (f->f_data) { - struct mbuf *m1; - u_int len; + if (f->f_data) { + struct mbuf *m1; + u_int len; - len = f->f_mlen - AOEHDRSZ; - if ((m1 = m_get(M_DONTWAIT, MT_DATA)) == NULL) { + len = f->f_mlen - AOEHDRSZ; + if ((m1 = m_get(M_NOWAIT, MT_DATA)) == NULL) { m_freem(m); + IPRINTK("m_get failed\n"); return (NULL); } m->m_next = m1; +#if __FreeBSD_version >= 1100028 + m1->m_ext.ext_cnt = NULL; +#else m1->m_ext.ref_cnt = NULL; +#endif MEXTADD(m1, f->f_data, len, nilfn, - NULL, 0, EXT_NET_DRV); +#if (__FreeBSD_version >= 800000) + f->f_data, +#endif + NULL, 0, EXT_NET_DRV); m1->m_len = len; m1->m_next = NULL; - } + } - return (m); + return (m); } int @@ -236,11 +278,20 @@ { struct mbuf *m; +#ifdef VIMAGE + CURVNET_SET_QUIET(d->ad_ifp->if_vnet); +#endif + m = frame_mbufinit(f); - if (m == NULL) - return (ENOMEM); + if (m == NULL) + return (ENOMEM); - return (ether_output_frame(d->ad_ifp, m)); + int ret = ether_output_frame(d->ad_ifp, m); +#ifdef VIMAGE + CURVNET_RESTORE(); +#endif + + return ret; } void @@ -250,6 +301,10 @@ struct aoe_cfghdr *ch; struct mbuf *m, *m0; struct ifnet *ifp; + +#ifdef VIMAGE + CURVNET_SET_QUIET(CRED_TO_VNET(curthread->td_ucred)); +#endif m0 = m_gethdr(M_NOWAIT, MT_DATA); if (m0 == NULL) { @@ -264,6 +319,7 @@ bzero(h, sizeof(*h) + sizeof(*ch)); m0->m_flags |= M_BCAST; + memset(h->ah_dst, 0xff, sizeof(h->ah_dst)); h->ah_type = htons(ETHERTYPE_AOE); h->ah_verfl = AOE_HVER; @@ -271,20 +327,26 @@ h->ah_minor = aoeminor; h->ah_cmd = AOECMD_CFG; + IFNET_RLOCK(); - TAILQ_FOREACH(ifp, &ifnet, if_link) { + TAILQ_FOREACH(ifp, &_aoenet_ifnet, if_link) { if (!is_aoe_netif(ifp)) continue; memcpy(h->ah_src, IFPADDR(ifp), sizeof(h->ah_src)); - m = m_copypacket(m0, M_DONTWAIT); + m = m_copypacket(m0, M_NOWAIT); if (m == NULL) { IPRINTK("m_copypacket failure\n"); continue; } ether_output_frame(ifp, m); + } IFNET_RUNLOCK(); +#ifdef VIMAGE + CURVNET_RESTORE(); +#endif + m_freem(m0); } @@ -297,8 +359,14 @@ u_int aoenet_maxsize(struct ifnet *ifp) { + + //IPRINTK("MTU %ld HDR %ld DEV_BSIZE %d\n",ifp->if_mtu, AOEHDRSZ, DEV_BSIZE); /* max payload size of packet based on interface mtu setting */ +#if __FreeBSD_version >= 1100030 + return ((ifp->if_mtu - AOEHDRSZ) & ~(DEV_BSIZE - 1)); +#else return ((ifp->if_data.ifi_mtu - AOEHDRSZ) & ~(DEV_BSIZE - 1)); +#endif } @@ -353,81 +421,105 @@ static void aoe_ether_input(struct ifnet *ifp, struct mbuf *m) { - struct ether_header *eh; - u_short etype; + struct ether_header *eh; + u_short etype; - /* - * Do consistency checks to verify assumptions - * made by code past this point. - */ - if ((m->m_flags & M_PKTHDR) == 0) { - if_printf(ifp, "discard frame w/o packet header\n"); - ifp->if_ierrors++; - m_freem(m); - return; + /* + * Do consistency checks to verify assumptions + * made by code past this point. + */ + if ((m->m_flags & M_PKTHDR) == 0) { + if_printf(ifp, "discard frame w/o packet header\n"); +#if __FreeBSD_version >= 1100036 + if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); +#else + ifp->if_ierrors++; +#endif + m_freem(m); + return; } - if (m->m_len < ETHER_HDR_LEN) { - if_printf(ifp, "discard frame w/o leading ethernet " - "header (len %u pkt len %u)\n", - m->m_len, m->m_pkthdr.len); - ifp->if_ierrors++; - m_freem(m); - return; - } - eh = mtod(m, struct ether_header *); - etype = ntohs(eh->ether_type); + if (m->m_len < ETHER_HDR_LEN) { + if_printf(ifp, "discard frame w/o leading ethernet " + "header (len %u pkt len %u)\n", + m->m_len, m->m_pkthdr.len); +#if __FreeBSD_version >= 1100036 + if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); +#else + ifp->if_ierrors++; +#endif + m_freem(m); + return; + } + eh = mtod(m, struct ether_header *); + etype = ntohs(eh->ether_type); if (etype != ETHERTYPE_AOE) { - (*old_ether_input)(ifp, m); + (*old_ether_inputs[ifp->if_index])(ifp, m); return; } - if (m->m_pkthdr.len > - ETHER_MAX_FRAME(ifp, etype, m->m_flags & M_HASFCS)) { - if_printf(ifp, "discard oversize frame " - "(ether type %x flags %x len %u > max %lu)\n", - etype, m->m_flags, m->m_pkthdr.len, - ETHER_MAX_FRAME(ifp, etype, - m->m_flags & M_HASFCS)); - ifp->if_ierrors++; - m_freem(m); - return; - } - if (m->m_pkthdr.rcvif == NULL) { - if_printf(ifp, "discard frame w/o interface pointer\n"); - ifp->if_ierrors++; - m_freem(m); - return; + if (m->m_pkthdr.len > + ETHER_MAX_FRAME(ifp, etype, m->m_flags & M_HASFCS)) { + /*if_printf(ifp, "discard oversize frame " + "(ether type %x flags %x len %u > max %u)\n", + etype, m->m_flags, m->m_pkthdr.len, + (int) ETHER_MAX_FRAME(ifp, etype, + m->m_flags & M_HASFCS));*/ +#if __FreeBSD_version >= 1100036 + if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); +#else + ifp->if_ierrors++; +#endif + m_freem(m); + return; } - /* - * Give bpf a chance at the AoE packet. - */ - BPF_MTAP(ifp, m); + if (m->m_pkthdr.rcvif == NULL) { + if_printf(ifp, "discard frame w/o interface pointer\n"); +#if __FreeBSD_version >= 1100036 + if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); +#else + ifp->if_ierrors++; +#endif + m_freem(m); + return; + } + /* + * Give bpf a chance at the AoE packet. + */ + BPF_MTAP(ifp, m); - if (ifp->if_flags & IFF_MONITOR) { - /* - * Interface marked for monitoring; discard packet. - */ - m_freem(m); - return; - } + if (ifp->if_flags & IFF_MONITOR) { + /* + * Interface marked for monitoring; discard packet. + */ + m_freem(m); + return; + } - /* If the CRC is still on the packet, trim it off. */ - if (m->m_flags & M_HASFCS) { - m_adj(m, -ETHER_CRC_LEN); - m->m_flags &= ~M_HASFCS; - } + /* If the CRC is still on the packet, trim it off. */ + if (m->m_flags & M_HASFCS) { + m_adj(m, -ETHER_CRC_LEN); + m->m_flags &= ~M_HASFCS; + } - ifp->if_ibytes += m->m_pkthdr.len; +#if __FreeBSD_version >= 1100036 + if_inc_counter(ifp, IFCOUNTER_IBYTES, m->m_pkthdr.len); +#else + ifp->if_ibytes += m->m_pkthdr.len; +#endif - if (ETHER_IS_MULTICAST(eh->ether_dhost)) { - if (bcmp(etherbroadcastaddr, eh->ether_dhost, - sizeof(etherbroadcastaddr)) == 0) - m->m_flags |= M_BCAST; - else - m->m_flags |= M_MCAST; - } - if (m->m_flags & (M_BCAST|M_MCAST)) - ifp->if_imcasts++; + if (ETHER_IS_MULTICAST(eh->ether_dhost)) { + if (bcmp(etherbroadcastaddr, eh->ether_dhost, + sizeof(etherbroadcastaddr)) == 0) + m->m_flags |= M_BCAST; + else + m->m_flags |= M_MCAST; + } + if (m->m_flags & (M_BCAST|M_MCAST)) +#if __FreeBSD_version >= 1100036 + if_inc_counter(ifp, IFCOUNTER_IMCASTS, 1); +#else + ifp->if_imcasts++; +#endif aoeintr(m); /* netisr_dispatch(NETISR_AOE, m); */ @@ -438,27 +530,36 @@ sysctl_aoe_iflist(SYSCTL_HANDLER_ARGS) { int error; + + #ifdef FORCE_NETWORK_HOOK struct ifnet *ifp; -#endif + IFNET_RLOCK(); + TAILQ_FOREACH(ifp, &_aoenet_ifnet, if_link) { + if (!is_aoe_netif(ifp)) + continue; + // restore the if_input + ifp->if_input = old_ether_inputs[ifp->if_index]; + } + IFNET_RUNLOCK(); +#endif error = sysctl_handle_string(oidp, arg1, arg2, req); #ifdef FORCE_NETWORK_HOOK IFNET_RLOCK(); - TAILQ_FOREACH(ifp, &ifnet, if_link) { - if (!is_aoe_netif(ifp)) { - if (ifp->if_input == aoe_ether_input) - ifp->if_input = old_ether_input; + TAILQ_FOREACH(ifp, &_aoenet_ifnet, if_link) { + if (!is_aoe_netif(ifp)) continue; - } - if (ifp->if_input != aoe_ether_input) - ifp->if_input = aoe_ether_input; - + // remember the if_input + old_ether_inputs[ifp->if_index] = ifp->if_input; + // now take it over + ifp->if_input = aoe_ether_input; } IFNET_RUNLOCK(); #endif /* FORCE_NETWORK_HOOK */ + // send broadcast to discover devices aoecmd_cfg(0xffff, 0xff); return (error); @@ -467,26 +568,7 @@ void aoenet_init(void) { -#ifdef FORCE_NETWORK_HOOK - struct ifnet *ifp; - - IFNET_RLOCK(); - TAILQ_FOREACH(ifp, &ifnet, if_link) { - switch (ifp->if_data.ifi_type) { - case IFT_ETHER: - case IFT_FASTETHER: - case IFT_GIGABITETHERNET: - break; - default: - continue; - } - if (old_ether_input == NULL) - old_ether_input = ifp->if_input; - else if (old_ether_input != ifp->if_input) - IPRINTK("ifp->if_input != ether_input\n"); - } - IFNET_RUNLOCK(); -#else +#ifndef FORCE_NETWORK_HOOK aoeintrq.ifq_maxlen = IFQ_MAXLEN; mtx_init(&aoeintrq.ifq_mtx, "aoe_inq", NULL, MTX_DEF); netisr_register(NETISR_AOE, aoeintr, &aoeintrq, NETISR_MPSAFE); @@ -498,19 +580,12 @@ { #ifdef FORCE_NETWORK_HOOK struct ifnet *ifp; - IFNET_RLOCK(); - TAILQ_FOREACH(ifp, &ifnet, if_link) { - switch (ifp->if_data.ifi_type) { - case IFT_ETHER: - case IFT_FASTETHER: - case IFT_GIGABITETHERNET: - break; - default: - continue; - } - if (ifp->if_input == aoe_ether_input) - ifp->if_input = old_ether_input; + TAILQ_FOREACH(ifp, &_aoenet_ifnet, if_link) { + if (!is_aoe_netif(ifp)) + continue; + // restore the if_input + ifp->if_input = old_ether_inputs[ifp->if_index]; } IFNET_RUNLOCK(); #else