diff options
author | julian <julian@FreeBSD.org> | 1999-10-26 11:40:23 +0000 |
---|---|---|
committer | julian <julian@FreeBSD.org> | 1999-10-26 11:40:23 +0000 |
commit | 226fbf47146cb040a886724dee6ba4250518539e (patch) | |
tree | d160098d30285050d8e8651b88c47461fc0a0099 | |
parent | 48eeb0662db3f5abb8727e7567fc64ec7468a9d1 (diff) | |
download | FreeBSD-src-226fbf47146cb040a886724dee6ba4250518539e.zip FreeBSD-src-226fbf47146cb040a886724dee6ba4250518539e.tar.gz |
Minor hack in the netgraph interface to ethernets.
-rw-r--r-- | sys/net/if_ethersubr.c | 71 |
1 files changed, 60 insertions, 11 deletions
diff --git a/sys/net/if_ethersubr.c b/sys/net/if_ethersubr.c index 04e3ea8..79d8b62 100644 --- a/sys/net/if_ethersubr.c +++ b/sys/net/if_ethersubr.c @@ -1133,29 +1133,78 @@ bad: /* * pass an mbuf out to the connected hook - */ + * More complicated than just an m_prepend, as it tries to save later nodes + * from needing to do lots of m_pullups. + */ static void ngether_send(struct arpcom *ac, struct ether_header *eh, struct mbuf *m) -{ +{ + int room; node_p node = AC2NG(ac); struct ether_header *eh2; - + if (node && LIST_FIRST(&(node->hooks))) { - M_PREPEND(m, sizeof(*eh), M_DONTWAIT); - if (m == 0) - return; - eh2 = mtod(m, struct ether_header *); /* - * Possibly 'eh' already points - * to the right place. + * Possibly the header is already on the front, */ - if (eh2 != eh) - bcopy(eh, eh2, sizeof(*eh)); + eh2 = mtod(m, struct ether_header *) - 1; + if ( eh == eh2) { + /* + * This is the case so just move the markers back to + * re-include it. We lucked out. + * This allows us to avoid a yucky m_pullup + * in later nodes if it works. + */ + m->m_len += sizeof(*eh); + m->m_data -= sizeof(*eh); + m->m_pkthdr.len += sizeof(*eh); + } else { + /* + * Alternatively there may be room even though + * it is stored somewhere else. If so, copy it in. + * This only safe because we KNOW that this packet has + * just been generated by an ethernet card, so there + * are no aliases to the buffer. (unlike in outgoing + * packets). + * Nearly all ethernet cards will end up producing mbufs + * that fall into these cases. So we are not optimising + * contorted cases. + */ + + if (m->m_flags & M_EXT) { + room = (mtod(m, caddr_t) - m->m_ext.ext_buf); + if (room > m->m_ext.ext_size) /* garbage */ + room = 0; /* fail immediatly */ + } else { + room = (mtod(m, caddr_t) - m->m_pktdat); + } + if (room > sizeof (*eh)) { + /* we have room, just copy it and adjust */ + m->m_len += sizeof(*eh); + m->m_data -= sizeof(*eh); + m->m_pkthdr.len += sizeof(*eh); + bcopy ((caddr_t)eh, (caddr_t)eh2, sizeof(*eh)); + } else { + /* + * Doing anything more is likely to get more + * expensive than it's worth.. + * it's probable that everything else is in one + * big lump. The next node will do an m_pullup() + * for exactly the amount of data it needs and + * hopefully everything after that will not + * need one. So let's just use m_prepend. + */ + m = m_prepend(m, MHLEN, M_DONTWAIT); + if (m == NULL) + return; + } + } ng_queue_data(LIST_FIRST(&(node->hooks)), m, NULL); } else { m_freem(m); } } + /* * do local shutdown processing.. * This node will refuse to go away, unless the hardware says to.. |