patch-2.1.8 linux/net/core/iovec.c
Next file: linux/net/core/skbuff.c
Previous file: linux/net/core/dev.c
Back to the patch index
Back to the overall index
- Lines: 153
- Date:
Sun Nov 3 11:04:43 1996
- Orig file:
v2.1.7/linux/net/core/iovec.c
- Orig date:
Tue Oct 29 19:58:49 1996
diff -u --recursive --new-file v2.1.7/linux/net/core/iovec.c linux/net/core/iovec.c
@@ -9,6 +9,8 @@
*
* Fixes:
* Andrew Lunn : Errors in iovec copying.
+ * Pedro Roque : Added memcpy_fromiovecend and
+ * csum_..._fromiovecend.
*/
@@ -17,8 +19,10 @@
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/net.h>
+#include <linux/in6.h>
#include <asm/uaccess.h>
-
+#include <asm/byteorder.h>
+#include <asm/checksum.h>
extern inline int min(int x, int y)
{
@@ -103,4 +107,131 @@
}
iov++;
}
+}
+
+
+/*
+ * For use with ip_build_xmit
+ */
+
+void memcpy_fromiovecend(unsigned char *kdata, struct iovec *iov, int offset,
+ int len)
+{
+ while(offset>0)
+ {
+ if (offset > iov->iov_len)
+ {
+ offset -= iov->iov_len;
+
+ }
+ else
+ {
+ u8 *base;
+ int copy;
+
+ base = iov->iov_base + offset;
+ copy = min(len, iov->iov_len - offset);
+ offset = 0;
+
+ copy_from_user(kdata, base, copy);
+ len-=copy;
+ kdata+=copy;
+ }
+ iov++;
+ }
+
+ while (len>0)
+ {
+ int copy=min(len, iov->iov_len);
+ copy_from_user(kdata, iov->iov_base, copy);
+ len-=copy;
+ kdata+=copy;
+ iov++;
+ }
+}
+
+/*
+ * And now for the all-in-one: copy and checksum from a user iovec
+ * directly to a datagram
+ * Calls to csum_partial but the last must be in 32 bit chunks
+ *
+ * ip_build_xmit must ensure that when fragmenting only the last
+ * call to this function will be unaligned also.
+ */
+
+unsigned int csum_partial_copy_fromiovecend(unsigned char *kdata,
+ struct iovec *iov, int offset,
+ int len, int csum)
+{
+ __u32 partial;
+ __u32 partial_cnt = 0;
+
+ while(offset>0)
+ {
+ if (offset > iov->iov_len)
+ {
+ offset -= iov->iov_len;
+
+ }
+ else
+ {
+ u8 *base;
+ int copy;
+
+ base = iov->iov_base + offset;
+ copy = min(len, iov->iov_len - offset);
+ offset = 0;
+
+ partial_cnt = copy % 4;
+ if (partial_cnt)
+ {
+ copy -= partial_cnt;
+ copy_from_user(&partial, base + copy,
+ partial_cnt);
+ }
+
+ csum = csum_partial_copy_fromuser(base, kdata,
+ copy, csum);
+
+ len -= copy + partial_cnt;
+ kdata += copy + partial_cnt;
+ }
+ iov++;
+ }
+
+ while (len>0)
+ {
+ u8 *base = iov->iov_base;
+ int copy=min(len, iov->iov_len);
+
+ if (partial_cnt)
+ {
+ int par_len = 4 - partial_cnt;
+
+ copy_from_user(&partial, base + partial_cnt, par_len);
+ csum = csum_partial((u8*) &partial, 4, csum);
+ base += par_len;
+ copy -= par_len;
+ partial_cnt = 0;
+ }
+
+ if (len - copy > 0)
+ {
+ partial_cnt = copy % 4;
+ if (partial_cnt)
+ {
+ copy -= partial_cnt;
+ copy_from_user(&partial, base + copy,
+ partial_cnt);
+ }
+ }
+
+ csum = csum_partial_copy_fromuser(base, kdata,
+ copy, csum);
+ len -= copy + partial_cnt;
+ kdata += copy + partial_cnt;
+ iov++;
+ }
+
+ return csum;
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov