Module Name: src
Committed By: tsutsui
Date: Sun Mar 29 07:33:53 UTC 2009
Modified Files:
src/sys/dev/ic: hme.c
Log Message:
Don't assume all RX packets have VLAN headers even if vlanif is configured.
Instead, always check ether_type and use appropriate offsets to adjust
the hardware RX sum value.
XXX: vlan(4) doesn't seem to use csum_data and csum_flags in mbufs anyway.
To generate a diff of this commit:
cvs rdiff -u -r1.73 -r1.74 src/sys/dev/ic/hme.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/dev/ic/hme.c
diff -u src/sys/dev/ic/hme.c:1.73 src/sys/dev/ic/hme.c:1.74
--- src/sys/dev/ic/hme.c:1.73 Mon Mar 16 12:02:00 2009
+++ src/sys/dev/ic/hme.c Sun Mar 29 07:33:52 2009
@@ -1,4 +1,4 @@
-/* $NetBSD: hme.c,v 1.73 2009/03/16 12:02:00 tsutsui Exp $ */
+/* $NetBSD: hme.c,v 1.74 2009/03/29 07:33:52 tsutsui Exp $ */
/*-
* Copyright (c) 1999 The NetBSD Foundation, Inc.
@@ -34,7 +34,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: hme.c,v 1.73 2009/03/16 12:02:00 tsutsui Exp $");
+__KERNEL_RCSID(0, "$NetBSD: hme.c,v 1.74 2009/03/29 07:33:52 tsutsui Exp $");
/* #define HMEDEBUG */
@@ -62,6 +62,7 @@
#include <net/if_media.h>
#ifdef INET
+#include <net/if_vlanvar.h>
#include <netinet/in.h>
#include <netinet/if_inarp.h>
#include <netinet/in_systm.h>
@@ -591,9 +592,8 @@
/* set h/w rx checksum start offset (# of half-words) */
#ifdef INET
- v |= (((ETHER_HDR_LEN + sizeof(struct ip) +
- ((sc->sc_ethercom.ec_capenable & ETHERCAP_VLAN_MTU) ?
- ETHER_VLAN_ENCAP_LEN : 0)) / 2) << HME_ERX_CFG_CSUMSHIFT) &
+ v |= (((ETHER_HDR_LEN + sizeof(struct ip)) / sizeof(uint16_t))
+ << HME_ERX_CFG_CSUMSHIFT) &
HME_ERX_CFG_CSUMSTART;
#endif
bus_space_write_4(t, erx, HME_ERXI_CFG, v);
@@ -721,24 +721,27 @@
/* hardware checksum */
if (ifp->if_csum_flags_rx & (M_CSUM_TCPv4 | M_CSUM_UDPv4)) {
struct ether_header *eh;
+ struct ether_vlan_header *evh;
struct ip *ip;
struct udphdr *uh;
uint16_t *opts;
int32_t hlen, pktlen;
uint32_t temp;
- if (sc->sc_ethercom.ec_capenable & ETHERCAP_VLAN_MTU) {
- pktlen = m0->m_pkthdr.len - ETHER_HDR_LEN -
- ETHER_VLAN_ENCAP_LEN;
- eh = (struct ether_header *) mtod(m0, void *) +
- ETHER_VLAN_ENCAP_LEN;
- } else {
+ eh = mtod(m0, struct ether_header *);
+ if (ntohs(eh->ether_type) == ETHERTYPE_IP) {
+ ip = (struct ip *)((char *)eh + ETHER_HDR_LEN);
pktlen = m0->m_pkthdr.len - ETHER_HDR_LEN;
- eh = mtod(m0, struct ether_header *);
- }
- if (ntohs(eh->ether_type) != ETHERTYPE_IP)
+ } else if (ntohs(eh->ether_type) == ETHERTYPE_VLAN) {
+ evh = (struct ether_vlan_header *)eh;
+ if (ntohs(evh->evl_proto != ETHERTYPE_IP))
+ goto swcsum;
+ ip = (struct ip *)((char *)eh + ETHER_HDR_LEN +
+ ETHER_VLAN_ENCAP_LEN);
+ pktlen = m0->m_pkthdr.len -
+ ETHER_HDR_LEN - ETHER_VLAN_ENCAP_LEN;
+ } else
goto swcsum;
- ip = (struct ip *) ((char *)eh + ETHER_HDR_LEN);
/* IPv4 only */
if (ip->ip_v != IPVERSION)
@@ -782,13 +785,18 @@
/* w/ M_CSUM_NO_PSEUDOHDR, the uncomplemented sum is expected */
m0->m_pkthdr.csum_data = (~flags) & HME_XD_RXCKSUM;
- /* if the pkt had ip options, we have to deduct them */
- if (hlen > sizeof(struct ip)) {
+ /*
+ * If data offset is different from RX cksum start offset,
+ * we have to deduct them.
+ */
+ temp = ((char *)ip + hlen) -
+ ((char *)eh + ETHER_HDR_LEN + sizeof(struct ip));
+ if (temp > 1) {
uint32_t optsum;
optsum = 0;
- temp = hlen - sizeof(struct ip);
- opts = (uint16_t *)((char *)ip + sizeof(struct ip));
+ opts = (uint16_t *)((char *)eh +
+ ETHER_HDR_LEN + sizeof(struct ip));
while (temp > 1) {
optsum += ntohs(*opts++);