Author: hselasky
Date: Thu Jul  3 10:49:46 2014
New Revision: 268209
URL: http://svnweb.freebsd.org/changeset/base/268209

Log:
  - Disable hardware checksumming until it is properly tested.
  - Don't discard frames if the dropped or error flag is set.
  - Don't remove the last 4-bytes of every packet.
  - Add extra range check for data position offset when receiving data.
  
  MFC after:    1 day
  PR:           191432

Modified:
  head/sys/dev/usb/net/if_axge.c

Modified: head/sys/dev/usb/net/if_axge.c
==============================================================================
--- head/sys/dev/usb/net/if_axge.c      Thu Jul  3 08:07:37 2014        
(r268208)
+++ head/sys/dev/usb/net/if_axge.c      Thu Jul  3 10:49:46 2014        
(r268209)
@@ -123,8 +123,8 @@ static int  axge_attach_post_sub(struct u
 static int     axge_ifmedia_upd(struct ifnet *);
 static void    axge_ifmedia_sts(struct ifnet *, struct ifmediareq *);
 static int     axge_ioctl(struct ifnet *, u_long, caddr_t);
-static int     axge_rx_frame(struct usb_ether *, struct usb_page_cache *, int);
-static int     axge_rxeof(struct usb_ether *, struct usb_page_cache *,
+static void    axge_rx_frame(struct usb_ether *, struct usb_page_cache *, int);
+static void    axge_rxeof(struct usb_ether *, struct usb_page_cache *,
                    unsigned int, unsigned int, uint32_t);
 static void    axge_csum_cfg(struct usb_ether *);
 
@@ -605,8 +605,7 @@ axge_bulk_read_callback(struct usb_xfer 
        switch (USB_GET_STATE(xfer)) {
        case USB_ST_TRANSFERRED:
                pc = usbd_xfer_get_frame(xfer, 0);
-               if (axge_rx_frame(ue, pc, actlen) != 0)
-                       goto tr_setup;
+               axge_rx_frame(ue, pc, actlen);
 
                /* FALLTHROUGH */
        case USB_ST_SETUP:
@@ -926,12 +925,11 @@ axge_ioctl(struct ifnet *ifp, u_long cmd
        return (error);
 }
 
-static int
+static void
 axge_rx_frame(struct usb_ether *ue, struct usb_page_cache *pc, int actlen)
 {
-       int error;
-       int pos;
-       int pkt_cnt;
+       uint32_t pos;
+       uint32_t pkt_cnt;
        uint32_t rxhdr;
        uint32_t pkt_hdr;
        uint32_t hdr_off;
@@ -939,10 +937,9 @@ axge_rx_frame(struct usb_ether *ue, stru
 
        /* verify we have enough data */
        if (actlen < (int)sizeof(rxhdr))
-               return (EINVAL);
+               return;
 
        pos = 0;
-       error = 0;
 
        usbd_copy_out(pc, actlen - sizeof(rxhdr), &rxhdr, sizeof(rxhdr));
        rxhdr = le32toh(rxhdr);
@@ -950,35 +947,36 @@ axge_rx_frame(struct usb_ether *ue, stru
        pkt_cnt = (uint16_t)rxhdr;
        hdr_off = (uint16_t)(rxhdr >> 16);
 
-       while (pkt_cnt > 0) {
+       while (pkt_cnt--) {
                /* verify the header offset */
                if ((int)(hdr_off + sizeof(pkt_hdr)) > actlen) {
-                       error = EINVAL;
+                       DPRINTF("End of packet headers\n");
+                       break;
+               }
+               if ((int)pos >= actlen) {
+                       DPRINTF("Data position reached end\n");
                        break;
                }
                usbd_copy_out(pc, hdr_off, &pkt_hdr, sizeof(pkt_hdr));
 
                pkt_hdr = le32toh(pkt_hdr);
                pktlen = (pkt_hdr >> 16) & 0x1fff;
-               if ((pkt_hdr & AXGE_RXHDR_CRC_ERR) ||
-                   (pkt_hdr & AXGE_RXHDR_DROP_ERR))
+               if (pkt_hdr & (AXGE_RXHDR_CRC_ERR | AXGE_RXHDR_DROP_ERR)) {
+                       DPRINTF("Dropped a packet\n");
                        ue->ue_ifp->if_ierrors++;
-               /* verify the data payload */
-               if (pktlen < 6 || (int)(pos + 2 + pktlen - 6) > actlen) {
-                       error = EINVAL;
-                       break;
                }
-               axge_rxeof(ue, pc, pos + 2, pktlen - 6, pkt_hdr);
+               if (pktlen >= 2 && (int)(pos + pktlen) <= actlen) {
+                       axge_rxeof(ue, pc, pos + 2, pktlen - 2, pkt_hdr);
+               } else {
+                       DPRINTF("Invalid packet pos=%d len=%d\n",
+                           (int)pos, (int)pktlen);
+               }
                pos += (pktlen + 7) & ~7;
                hdr_off += sizeof(pkt_hdr);
-               pkt_cnt--;
        }
-       if (error != 0)
-               ue->ue_ifp->if_ierrors++;
-       return (error);
 }
 
-static int
+static void
 axge_rxeof(struct usb_ether *ue, struct usb_page_cache *pc,
     unsigned int offset, unsigned int len, uint32_t pkt_hdr)
 {
@@ -988,37 +986,34 @@ axge_rxeof(struct usb_ether *ue, struct 
        ifp = ue->ue_ifp;
        if (len < ETHER_HDR_LEN || len > MCLBYTES - ETHER_ALIGN) {
                ifp->if_ierrors++;
-               return (EINVAL);
+               return;
        }
 
        m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
        if (m == NULL) {
                ifp->if_iqdrops++;
-               return (ENOMEM);
+               return;
        }
-       m->m_len = m->m_pkthdr.len = MCLBYTES;
+       m->m_pkthdr.rcvif = ifp;
+       m->m_len = m->m_pkthdr.len = len + ETHER_ALIGN;
        m_adj(m, ETHER_ALIGN);
 
        usbd_copy_out(pc, offset, mtod(m, uint8_t *), len);
 
        ifp->if_ipackets++;
-       m->m_pkthdr.rcvif = ifp;
-       m->m_pkthdr.len = m->m_len = len;
-
+#if 0
        if ((pkt_hdr & (AXGE_RXHDR_L4CSUM_ERR | AXGE_RXHDR_L3CSUM_ERR)) == 0) {
-               m->m_pkthdr.csum_flags |= CSUM_IP_CHECKED | CSUM_IP_VALID;
                if ((pkt_hdr & AXGE_RXHDR_L4_TYPE_MASK) ==
                    AXGE_RXHDR_L4_TYPE_TCP ||
                    (pkt_hdr & AXGE_RXHDR_L4_TYPE_MASK) ==
                    AXGE_RXHDR_L4_TYPE_UDP) {
                        m->m_pkthdr.csum_flags |= CSUM_DATA_VALID |
-                           CSUM_PSEUDO_HDR;
+                           CSUM_PSEUDO_HDR | CSUM_IP_CHECKED | CSUM_IP_VALID;
                        m->m_pkthdr.csum_data = 0xffff;
                }
        }
-
+#endif
        _IF_ENQUEUE(&ue->ue_rxq, m);
-       return (0);
 }
 
 static void
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to