patch-2.4.0-test9 linux/drivers/net/sk98lin/skcsum.c
Next file: linux/drivers/net/sk98lin/skge.c
Previous file: linux/drivers/net/sk98lin/skaddr.c
Back to the patch index
Back to the overall index
- Lines: 326
- Date:
Fri Sep 15 14:34:19 2000
- Orig file:
v2.4.0-test8/linux/drivers/net/sk98lin/skcsum.c
- Orig date:
Tue Nov 23 10:15:42 1999
diff -u --recursive --new-file v2.4.0-test8/linux/drivers/net/sk98lin/skcsum.c linux/drivers/net/sk98lin/skcsum.c
@@ -2,19 +2,17 @@
*
* Name: skcsum.c
* Project: GEnesis, PCI Gigabit Ethernet Adapter
- * Version: $Revision: 1.3 $
- * Date: $Date: 1999/05/10 08:39:33 $
+ * Version: $Revision: 1.7 $
+ * Date: $Date: 2000/06/29 13:17:05 $
* Purpose: Store/verify Internet checksum in send/receive packets.
*
******************************************************************************/
/******************************************************************************
*
- * (C)Copyright 1998,1999 SysKonnect,
+ * (C)Copyright 1998-2000 SysKonnect,
* a business unit of Schneider & Koch & Co. Datensysteme GmbH.
*
- * See the file "skge.c" for further information.
- *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
@@ -29,6 +27,23 @@
* History:
*
* $Log: skcsum.c,v $
+ * Revision 1.7 2000/06/29 13:17:05 rassmann
+ * Corrected reception of a packet with UDP checksum == 0 (which means there
+ * is no UDP checksum).
+ *
+ * Revision 1.6 2000/02/21 12:35:10 cgoos
+ * Fixed license header comment.
+ *
+ * Revision 1.5 2000/02/21 11:05:19 cgoos
+ * Merged changes back to common source.
+ * Fixed rx path for BIG ENDIAN architecture.
+ *
+ * Revision 1.1 1999/07/26 15:28:12 mkarl
+ * added return SKCS_STATUS_IP_CSUM_ERROR_UDP and
+ * SKCS_STATUS_IP_CSUM_ERROR_TCP to pass the NidsTester
+ * changed from common source to windows specific source
+ * therefore restarting with v1.0
+ *
* Revision 1.3 1999/05/10 08:39:33 mkarl
* prevent overflows in SKCS_HTON16
* fixed a bug in pseudo header checksum calculation
@@ -48,7 +63,7 @@
#ifndef lint
static const char SysKonnectFileId[] = "@(#)"
- "$Id: skcsum.c,v 1.3 1999/05/10 08:39:33 mkarl Exp $"
+ "$Id: skcsum.c,v 1.7 2000/06/29 13:17:05 rassmann Exp $"
" (C) SysKonnect.";
#endif /* !lint */
@@ -94,13 +109,13 @@
/* defines ********************************************************************/
/* The size of an Ethernet MAC header. */
-#define SKCS_ETHERNET_MAC_HEADER_SIZE (6+6+2)
+#define SKCS_ETHERNET_MAC_HEADER_SIZE (6+6+2)
/* The size of the used topology's MAC header. */
#define SKCS_MAC_HEADER_SIZE SKCS_ETHERNET_MAC_HEADER_SIZE
/* The size of the IP header without any option fields. */
-#define SKCS_IP_HEADER_SIZE 20
+#define SKCS_IP_HEADER_SIZE 20
/*
* Field offsets within the IP header.
@@ -110,23 +125,31 @@
#define SKCS_OFS_IP_HEADER_VERSION_AND_LENGTH 0
/* "Total Length". */
-#define SKCS_OFS_IP_TOTAL_LENGTH 2
+#define SKCS_OFS_IP_TOTAL_LENGTH 2
/* "Flags" "Fragment Offset". */
#define SKCS_OFS_IP_FLAGS_AND_FRAGMENT_OFFSET 6
/* "Next Level Protocol" identifier. */
-#define SKCS_OFS_IP_NEXT_LEVEL_PROTOCOL 9
+#define SKCS_OFS_IP_NEXT_LEVEL_PROTOCOL 9
/* Source IP address. */
-#define SKCS_OFS_IP_SOURCE_ADDRESS 12
+#define SKCS_OFS_IP_SOURCE_ADDRESS 12
/* Destination IP address. */
-#define SKCS_OFS_IP_DESTINATION_ADDRESS 16
+#define SKCS_OFS_IP_DESTINATION_ADDRESS 16
+
+
+/*
+ * Field offsets within the UDP header.
+ */
+
+/* UDP checksum. */
+#define SKCS_OFS_UDP_CHECKSUM 6
/* IP "Next Level Protocol" identifiers (see RFC 790). */
-#define SKCS_PROTO_ID_TCP 6 /* Transport Control Protocol */
-#define SKCS_PROTO_ID_UDP 17 /* User Datagram Protocol */
+#define SKCS_PROTO_ID_TCP 6 /* Transport Control Protocol */
+#define SKCS_PROTO_ID_UDP 17 /* User Datagram Protocol */
/* IP "Don't Fragment" bit. */
#define SKCS_IP_DONT_FRAGMENT SKCS_HTON16(0x4000)
@@ -224,8 +247,8 @@
* of the TCP or UDP pseudo header is returned here.
*/
void SkCsGetSendInfo(
-SK_AC *pAc, /* Adapter context struct. */
-void *pIpHeader, /* IP header. */
+SK_AC *pAc, /* Adapter context struct. */
+void *pIpHeader, /* IP header. */
SKCS_PACKET_INFO *pPacketInfo) /* Packet information struct. */
{
/* Internet Header Version found in IP header. */
@@ -397,7 +420,8 @@
SKCS_OC_ADD(pPacketInfo->PseudoHeaderChecksum, PseudoHeaderChecksum, 0);
NextLevelProtoStats->TxOkCts++; /* Success. */
-}
+} /* SkCsGetSendInfo */
+
/******************************************************************************
*
@@ -415,7 +439,8 @@
* pAc - Pointer to adapter context struct.
*
* pIpHeader - Pointer to IP header. Must be at least the length in bytes
- * of the received IP header including any option fields.
+ * of the received IP header including any option fields. For UDP packets,
+ * 8 additional bytes are needed to access the UDP checksum.
*
* Note: The actual length of the IP header is stored in the lower four
* bits of the first octet of the IP header as the number of 4-byte words,
@@ -431,18 +456,20 @@
* Returns:
* SKCS_STATUS_UNKNOWN_IP_VERSION - Not an IP v4 frame.
* SKCS_STATUS_IP_CSUM_ERROR - IP checksum error.
+ * SKCS_STATUS_IP_CSUM_ERROR_TCP - IP checksum error in TCP frame.
+ * SKCS_STATUS_IP_CSUM_ERROR_UDP - IP checksum error in UDP frame
* SKCS_STATUS_IP_FRAGMENT - IP fragment (IP checksum ok).
* SKCS_STATUS_IP_CSUM_OK - IP checksum ok (not a TCP or UDP frame).
* SKCS_STATUS_TCP_CSUM_ERROR - TCP checksum error (IP checksum ok).
* SKCS_STATUS_UDP_CSUM_ERROR - UDP checksum error (IP checksum ok).
* SKCS_STATUS_TCP_CSUM_OK - IP and TCP checksum ok.
* SKCS_STATUS_UDP_CSUM_OK - IP and UDP checksum ok.
+ * SKCS_STATUS_IP_CSUM_OK_NO_UDP - IP checksum OK and no UDP checksum.
*
- * Note: The SKCS_STATUS_XXX values returned here are *not* defined by
- * the CSUM module but must be defined in some header file by the module
- * using CSUM. In this way, the calling module can assign return values
- * for its own needs, e.g. by assigning bit flags to the individual
- * protocols.
+ * Note: If SKCS_OVERWRITE_STATUS is defined, the SKCS_STATUS_XXX values
+ * returned here can be defined in some header file by the module using CSUM.
+ * In this way, the calling module can assign return values for its own needs,
+ * e.g. by assigning bit flags to the individual protocols.
*/
SKCS_STATUS SkCsGetReceiveInfo(
SK_AC *pAc, /* Adapter context struct. */
@@ -544,30 +571,36 @@
/* Adjust the IP header and IP data checksums. */
- SKCS_OC_ADD(IpHeaderChecksum,
- IpHeaderChecksum, IpOptionsChecksum);
+ SKCS_OC_ADD(IpHeaderChecksum, IpHeaderChecksum, IpOptionsChecksum);
- SKCS_OC_SUB(IpDataChecksum,
- IpDataChecksum, IpOptionsChecksum);
+ SKCS_OC_SUB(IpDataChecksum, IpDataChecksum, IpOptionsChecksum);
}
- /* Check if the IP header checksum is ok. */
/*
- * NOTE: We must check the IP header checksum even if the caller does
- * not want us to do so because we cannot do any further processing of
- * the packet without a valid IP checksum.
+ * Check if the IP header checksum is ok.
+ *
+ * NOTE: We must check the IP header checksum even if the caller just wants
+ * us to check upper-layer checksums, because we cannot do any further
+ * processing of the packet without a valid IP checksum.
*/
+
+ /* Get the next level protocol identifier. */
+
+ NextLevelProtocol = *(SK_U8 *)
+ SKCS_IDX(pIpHeader, SKCS_OFS_IP_NEXT_LEVEL_PROTOCOL);
if (IpHeaderChecksum != 0xFFFF) {
pAc->Csum.ProtoStats[SKCS_PROTO_STATS_IP].RxErrCts++;
+ /* the NDIS tester wants to know the upper level protocol too */
+ if (NextLevelProtocol == SKCS_PROTO_ID_TCP) {
+ return(SKCS_STATUS_IP_CSUM_ERROR_TCP);
+ }
+ else if (NextLevelProtocol == SKCS_PROTO_ID_UDP) {
+ return(SKCS_STATUS_IP_CSUM_ERROR_UDP);
+ }
return (SKCS_STATUS_IP_CSUM_ERROR);
}
- /* Get the next level protocol identifier. */
-
- NextLevelProtocol =
- *(SK_U8 *) SKCS_IDX(pIpHeader, SKCS_OFS_IP_NEXT_LEVEL_PROTOCOL);
-
/*
* Check if this is a TCP or UDP frame and if we should calculate the
* TCP/UDP pseudo header checksum.
@@ -579,14 +612,12 @@
if ((pAc->Csum.ReceiveFlags & SKCS_PROTO_TCP) != 0 &&
NextLevelProtocol == SKCS_PROTO_ID_TCP) {
/* TCP/IP frame. */
- NextLevelProtoStats =
- &pAc->Csum.ProtoStats[SKCS_PROTO_STATS_TCP];
+ NextLevelProtoStats = &pAc->Csum.ProtoStats[SKCS_PROTO_STATS_TCP];
}
else if ((pAc->Csum.ReceiveFlags & SKCS_PROTO_UDP) != 0 &&
NextLevelProtocol == SKCS_PROTO_ID_UDP) {
/* UDP/IP frame. */
- NextLevelProtoStats =
- &pAc->Csum.ProtoStats[SKCS_PROTO_STATS_UDP];
+ NextLevelProtoStats = &pAc->Csum.ProtoStats[SKCS_PROTO_STATS_UDP];
}
else {
/*
@@ -615,6 +646,24 @@
}
/*
+ * 08-May-2000 ra
+ *
+ * From RFC 768 (UDP)
+ * If the computed checksum is zero, it is transmitted as all ones (the
+ * equivalent in one's complement arithmetic). An all zero transmitted
+ * checksum value means that the transmitter generated no checksum (for
+ * debugging or for higher level protocols that don't care).
+ */
+
+ if (NextLevelProtocol == SKCS_PROTO_ID_UDP &&
+ *(SK_U16*)SKCS_IDX(pIpHeader, IpHeaderLength + 6) == 0x0000) {
+
+ NextLevelProtoStats->RxOkCts++;
+
+ return (SKCS_STATUS_IP_CSUM_OK_NO_UDP);
+ }
+
+ /*
* Calculate the TCP/UDP checksum.
*/
@@ -639,7 +688,7 @@
SKCS_OFS_IP_DESTINATION_ADDRESS + 0) +
(unsigned long) *(SK_U16 *) SKCS_IDX(pIpHeader,
SKCS_OFS_IP_DESTINATION_ADDRESS + 2) +
- (unsigned long) (NextLevelProtocol << 8) +
+ (unsigned long) SKCS_HTON16(NextLevelProtocol) +
(unsigned long) SKCS_HTON16(IpDataLength) +
/* Add the TCP/UDP header checksum. */
@@ -672,7 +721,8 @@
return (NextLevelProtocol == SKCS_PROTO_ID_TCP ?
SKCS_STATUS_TCP_CSUM_ERROR : SKCS_STATUS_UDP_CSUM_ERROR);
-}
+} /* SkCsGetReceiveInfo */
+
/******************************************************************************
*
@@ -702,7 +752,7 @@
* Returns the two hardware checksum start offsets.
*/
void SkCsSetReceiveFlags(
-SK_AC *pAc, /* Adapter context struct. */
+SK_AC *pAc, /* Adapter context struct. */
unsigned ReceiveFlags, /* New receive flags. */
unsigned *pChecksum1Offset, /* Offset for hardware checksum 1. */
unsigned *pChecksum2Offset) /* Offset for hardware checksum 2. */
@@ -719,9 +769,10 @@
* if there are any IP header options in the actual packet.
*/
*pChecksum2Offset = SKCS_MAC_HEADER_SIZE + SKCS_IP_HEADER_SIZE;
-}
+} /* SkCsSetReceiveFlags */
#ifndef SkCsCalculateChecksum
+
/******************************************************************************
*
* SkCsCalculateChecksum - calculate checksum for specified data
@@ -783,7 +834,8 @@
/* Note: All bits beyond the 16-bit limit are now zero. */
return ((unsigned) Checksum);
-}
+} /* SkCsCalculateChecksum */
+
#endif /* SkCsCalculateChecksum */
/******************************************************************************
@@ -833,7 +885,7 @@
memset(&pAc->Csum.ProtoStats[0], 0,
sizeof(pAc->Csum.ProtoStats));
}
- else { /* Clear for individual protocol. */
+ else { /* Clear for individual protocol. */
memset(&pAc->Csum.ProtoStats[ProtoIndex], 0,
sizeof(pAc->Csum.ProtoStats[ProtoIndex]));
}
@@ -842,6 +894,6 @@
break;
}
return (0); /* Success. */
-}
+} /* SkCsEvent */
#endif /* SK_USE_CSUM */
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)