the main change here is to defer chopping the ethernet header off
the frame until just before the protocol input function is called.
this means we don't have to reattach it for pppoe.

ok?

Index: if_ethersubr.c
===================================================================
RCS file: /cvs/src/sys/net/if_ethersubr.c,v
retrieving revision 1.249
diff -u -p -r1.249 if_ethersubr.c
--- if_ethersubr.c      9 Jan 2018 06:24:15 -0000       1.249
+++ if_ethersubr.c      9 Jan 2018 06:32:39 -0000
@@ -315,12 +315,9 @@ int
 ether_input(struct ifnet *ifp, struct mbuf *m, void *cookie)
 {
        struct ether_header *eh;
-       struct niqueue *inq;
+       void (*input)(struct ifnet *, struct mbuf *);
        u_int16_t etype;
        struct arpcom *ac;
-#if NPPPOE > 0
-       struct ether_header *eh_tmp;
-#endif
 
        /* Drop short frames */
        if (m->m_len < ETHER_HDR_LEN)
@@ -328,7 +325,6 @@ ether_input(struct ifnet *ifp, struct mb
 
        ac = (struct arpcom *)ifp;
        eh = mtod(m, struct ether_header *);
-       m_adj(m, ETHER_HDR_LEN);
 
        if (ETHER_IS_MULTICAST(eh->ether_dhost)) {
                /*
@@ -376,45 +372,34 @@ ether_input(struct ifnet *ifp, struct mb
 
        switch (etype) {
        case ETHERTYPE_IP:
-               ipv4_input(ifp, m);
-               return (1);
+               input = ipv4_input;
+               break;
 
        case ETHERTYPE_ARP:
                if (ifp->if_flags & IFF_NOARP)
                        goto dropanyway;
-               arpinput(ifp, m);
-               return (1);
+               input = arpinput;
+               break;
 
        case ETHERTYPE_REVARP:
                if (ifp->if_flags & IFF_NOARP)
                        goto dropanyway;
-               revarpinput(ifp, m);
-               return (1);
+               input = revarpinput;
+               break;
 
 #ifdef INET6
        /*
         * Schedule IPv6 software interrupt for incoming IPv6 packet.
         */
        case ETHERTYPE_IPV6:
-               ipv6_input(ifp, m);
-               return (1);
+               input = ipv6_input;
+               break;
 #endif /* INET6 */
 #if NPPPOE > 0 || defined(PIPEX)
        case ETHERTYPE_PPPOEDISC:
        case ETHERTYPE_PPPOE:
                if (m->m_flags & (M_MCAST | M_BCAST))
                        goto dropanyway;
-               M_PREPEND(m, sizeof(*eh), M_DONTWAIT);
-               if (m == NULL)
-                       return (1);
-
-               eh_tmp = mtod(m, struct ether_header *);
-               /*
-                * danger!
-                * eh_tmp and eh may overlap because eh
-                * is stolen from the mbuf above.
-                */
-               memmove(eh_tmp, eh, sizeof(struct ether_header));
 #ifdef PIPEX
                if (pipex_enable) {
                        struct pipex_session *session;
@@ -426,22 +411,23 @@ ether_input(struct ifnet *ifp, struct mb
                }
 #endif
                if (etype == ETHERTYPE_PPPOEDISC)
-                       inq = &pppoediscinq;
+                       niq_enqueue(&pppoediscinq, m);
                else
-                       inq = &pppoeinq;
-               break;
+                       niq_enqueue(&pppoeinq, m);
+               return (1);
 #endif
 #ifdef MPLS
        case ETHERTYPE_MPLS:
        case ETHERTYPE_MPLS_MCAST:
-               mpls_input(ifp, m);
-               return (1);
+               input = mpls_input;
+               break;
 #endif
        default:
                goto dropanyway;
        }
 
-       niq_enqueue(inq, m);
+       m_adj(m, sizeof(*eh));
+       (*input)(ifp, m);
        return (1);
 dropanyway:
        m_freem(m);

Reply via email to