- 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
This commit is contained in:
parent
9f9f2874f6
commit
da0fdeefee
@ -123,8 +123,8 @@ static int axge_attach_post_sub(struct usb_ether *);
|
||||
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 *xfer, usb_error_t error)
|
||||
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, caddr_t data)
|
||||
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, struct usb_page_cache *pc, int actlen)
|
||||
|
||||
/* 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, struct usb_page_cache *pc, int actlen)
|
||||
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 usb_page_cache *pc,
|
||||
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
|
||||
|
Loading…
x
Reference in New Issue
Block a user