From 2df15fffc612b53b2c8e4ff3c981a82441bc00ae Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sun, 30 Oct 2005 20:44:37 +1100 Subject: [PADLOCK] Fix sparse warning about 1-bit signed bit-field Change the bit-field in struct cword to unsigned to shut sparse up. Signed-off-by: Herbert Xu --- drivers/crypto/padlock.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/crypto/padlock.h b/drivers/crypto/padlock.h index 3cf2b7a..b78489b 100644 --- a/drivers/crypto/padlock.h +++ b/drivers/crypto/padlock.h @@ -17,7 +17,7 @@ /* Control word. */ struct cword { - int __attribute__ ((__packed__)) + unsigned int __attribute__ ((__packed__)) rounds:4, algo:3, keygen:1, -- cgit v1.1 From 06ace7a9bafeb9047352707eb79e8eaa0dfdf5f2 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sun, 30 Oct 2005 21:25:15 +1100 Subject: [CRYPTO] Use standard byte order macros wherever possible A lot of crypto code needs to read/write a 32-bit/64-bit words in a specific gender. Many of them open code them by reading/writing one byte at a time. This patch converts all the applicable usages over to use the standard byte order macros. This is based on a previous patch by Denis Vlasenko. Signed-off-by: Herbert Xu --- arch/i386/crypto/aes.c | 44 ++++++++++---------- arch/x86_64/crypto/aes.c | 23 +++++------ crypto/aes.c | 60 ++++++++++++++-------------- crypto/anubis.c | 38 ++++++------------ crypto/blowfish.c | 2 + crypto/cast5.c | 46 +++++++++------------ crypto/cast6.c | 82 +++++++++++++++----------------------- crypto/crc32c.c | 1 + crypto/des.c | 2 + crypto/khazad.c | 45 +++++---------------- crypto/md4.c | 1 + crypto/md5.c | 1 + crypto/michael_mic.c | 40 ++++++++----------- crypto/serpent.c | 1 + crypto/sha1.c | 28 ++++--------- crypto/sha256.c | 31 +++++---------- crypto/sha512.c | 54 ++++++------------------- crypto/tea.c | 95 ++++++++++++++++++++++---------------------- crypto/tgr192.c | 64 ++++++++--------------------- crypto/twofish.c | 12 ++++-- crypto/wp512.c | 32 ++++----------- drivers/crypto/padlock-aes.c | 24 +++++------ 22 files changed, 285 insertions(+), 441 deletions(-) diff --git a/arch/i386/crypto/aes.c b/arch/i386/crypto/aes.c index 88ee85c..1deb9ff 100644 --- a/arch/i386/crypto/aes.c +++ b/arch/i386/crypto/aes.c @@ -36,6 +36,8 @@ * Copyright (c) 2004 Red Hat, Inc., James Morris * */ + +#include #include #include #include @@ -59,7 +61,6 @@ struct aes_ctx { }; #define WPOLY 0x011b -#define u32_in(x) le32_to_cpup((const __le32 *)(x)) #define bytes2word(b0, b1, b2, b3) \ (((u32)(b3) << 24) | ((u32)(b2) << 16) | ((u32)(b1) << 8) | (b0)) @@ -393,13 +394,14 @@ aes_set_key(void *ctx_arg, const u8 *in_key, unsigned int key_len, u32 *flags) int i; u32 ss[8]; struct aes_ctx *ctx = ctx_arg; + const __le32 *key = (const __le32 *)in_key; /* encryption schedule */ - ctx->ekey[0] = ss[0] = u32_in(in_key); - ctx->ekey[1] = ss[1] = u32_in(in_key + 4); - ctx->ekey[2] = ss[2] = u32_in(in_key + 8); - ctx->ekey[3] = ss[3] = u32_in(in_key + 12); + ctx->ekey[0] = ss[0] = le32_to_cpu(key[0]); + ctx->ekey[1] = ss[1] = le32_to_cpu(key[1]); + ctx->ekey[2] = ss[2] = le32_to_cpu(key[2]); + ctx->ekey[3] = ss[3] = le32_to_cpu(key[3]); switch(key_len) { case 16: @@ -410,8 +412,8 @@ aes_set_key(void *ctx_arg, const u8 *in_key, unsigned int key_len, u32 *flags) break; case 24: - ctx->ekey[4] = ss[4] = u32_in(in_key + 16); - ctx->ekey[5] = ss[5] = u32_in(in_key + 20); + ctx->ekey[4] = ss[4] = le32_to_cpu(key[4]); + ctx->ekey[5] = ss[5] = le32_to_cpu(key[5]); for (i = 0; i < 7; i++) ke6(ctx->ekey, i); kel6(ctx->ekey, 7); @@ -419,10 +421,10 @@ aes_set_key(void *ctx_arg, const u8 *in_key, unsigned int key_len, u32 *flags) break; case 32: - ctx->ekey[4] = ss[4] = u32_in(in_key + 16); - ctx->ekey[5] = ss[5] = u32_in(in_key + 20); - ctx->ekey[6] = ss[6] = u32_in(in_key + 24); - ctx->ekey[7] = ss[7] = u32_in(in_key + 28); + ctx->ekey[4] = ss[4] = le32_to_cpu(key[4]); + ctx->ekey[5] = ss[5] = le32_to_cpu(key[5]); + ctx->ekey[6] = ss[6] = le32_to_cpu(key[6]); + ctx->ekey[7] = ss[7] = le32_to_cpu(key[7]); for (i = 0; i < 6; i++) ke8(ctx->ekey, i); kel8(ctx->ekey, 6); @@ -436,10 +438,10 @@ aes_set_key(void *ctx_arg, const u8 *in_key, unsigned int key_len, u32 *flags) /* decryption schedule */ - ctx->dkey[0] = ss[0] = u32_in(in_key); - ctx->dkey[1] = ss[1] = u32_in(in_key + 4); - ctx->dkey[2] = ss[2] = u32_in(in_key + 8); - ctx->dkey[3] = ss[3] = u32_in(in_key + 12); + ctx->dkey[0] = ss[0] = le32_to_cpu(key[0]); + ctx->dkey[1] = ss[1] = le32_to_cpu(key[1]); + ctx->dkey[2] = ss[2] = le32_to_cpu(key[2]); + ctx->dkey[3] = ss[3] = le32_to_cpu(key[3]); switch (key_len) { case 16: @@ -450,8 +452,8 @@ aes_set_key(void *ctx_arg, const u8 *in_key, unsigned int key_len, u32 *flags) break; case 24: - ctx->dkey[4] = ff(ss[4] = u32_in(in_key + 16)); - ctx->dkey[5] = ff(ss[5] = u32_in(in_key + 20)); + ctx->dkey[4] = ff(ss[4] = le32_to_cpu(key[4])); + ctx->dkey[5] = ff(ss[5] = le32_to_cpu(key[5])); kdf6(ctx->dkey, 0); for (i = 1; i < 7; i++) kd6(ctx->dkey, i); @@ -459,10 +461,10 @@ aes_set_key(void *ctx_arg, const u8 *in_key, unsigned int key_len, u32 *flags) break; case 32: - ctx->dkey[4] = ff(ss[4] = u32_in(in_key + 16)); - ctx->dkey[5] = ff(ss[5] = u32_in(in_key + 20)); - ctx->dkey[6] = ff(ss[6] = u32_in(in_key + 24)); - ctx->dkey[7] = ff(ss[7] = u32_in(in_key + 28)); + ctx->dkey[4] = ff(ss[4] = le32_to_cpu(key[4])); + ctx->dkey[5] = ff(ss[5] = le32_to_cpu(key[5])); + ctx->dkey[6] = ff(ss[6] = le32_to_cpu(key[6])); + ctx->dkey[7] = ff(ss[7] = le32_to_cpu(key[7])); kdf8(ctx->dkey, 0); for (i = 1; i < 6; i++) kd8(ctx->dkey, i); diff --git a/arch/x86_64/crypto/aes.c b/arch/x86_64/crypto/aes.c index acfdaa2..1999685 100644 --- a/arch/x86_64/crypto/aes.c +++ b/arch/x86_64/crypto/aes.c @@ -74,8 +74,6 @@ static inline u8 byte(const u32 x, const unsigned n) return x >> (n << 3); } -#define u32_in(x) le32_to_cpu(*(const __le32 *)(x)) - struct aes_ctx { u32 key_length; @@ -234,6 +232,7 @@ static int aes_set_key(void *ctx_arg, const u8 *in_key, unsigned int key_len, u32 *flags) { struct aes_ctx *ctx = ctx_arg; + const __le32 *key = (const __le32 *)in_key; u32 i, j, t, u, v, w; if (key_len != 16 && key_len != 24 && key_len != 32) { @@ -243,10 +242,10 @@ static int aes_set_key(void *ctx_arg, const u8 *in_key, unsigned int key_len, ctx->key_length = key_len; - D_KEY[key_len + 24] = E_KEY[0] = u32_in(in_key); - D_KEY[key_len + 25] = E_KEY[1] = u32_in(in_key + 4); - D_KEY[key_len + 26] = E_KEY[2] = u32_in(in_key + 8); - D_KEY[key_len + 27] = E_KEY[3] = u32_in(in_key + 12); + D_KEY[key_len + 24] = E_KEY[0] = le32_to_cpu(key[0]); + D_KEY[key_len + 25] = E_KEY[1] = le32_to_cpu(key[1]); + D_KEY[key_len + 26] = E_KEY[2] = le32_to_cpu(key[2]); + D_KEY[key_len + 27] = E_KEY[3] = le32_to_cpu(key[3]); switch (key_len) { case 16: @@ -256,17 +255,17 @@ static int aes_set_key(void *ctx_arg, const u8 *in_key, unsigned int key_len, break; case 24: - E_KEY[4] = u32_in(in_key + 16); - t = E_KEY[5] = u32_in(in_key + 20); + E_KEY[4] = le32_to_cpu(key[4]); + t = E_KEY[5] = le32_to_cpu(key[5]); for (i = 0; i < 8; ++i) loop6 (i); break; case 32: - E_KEY[4] = u32_in(in_key + 16); - E_KEY[5] = u32_in(in_key + 20); - E_KEY[6] = u32_in(in_key + 24); - t = E_KEY[7] = u32_in(in_key + 28); + E_KEY[4] = le32_to_cpu(key[4]); + E_KEY[5] = le32_to_cpu(key[5]); + E_KEY[6] = le32_to_cpu(key[6]); + t = E_KEY[7] = le32_to_cpu(key[7]); for (i = 0; i < 7; ++i) loop8(i); break; diff --git a/crypto/aes.c b/crypto/aes.c index 5df9288..35a11de 100644 --- a/crypto/aes.c +++ b/crypto/aes.c @@ -73,9 +73,6 @@ byte(const u32 x, const unsigned n) return x >> (n << 3); } -#define u32_in(x) le32_to_cpu(*(const u32 *)(x)) -#define u32_out(to, from) (*(u32 *)(to) = cpu_to_le32(from)) - struct aes_ctx { int key_length; u32 E[60]; @@ -256,6 +253,7 @@ static int aes_set_key(void *ctx_arg, const u8 *in_key, unsigned int key_len, u32 *flags) { struct aes_ctx *ctx = ctx_arg; + const __le32 *key = (const __le32 *)in_key; u32 i, t, u, v, w; if (key_len != 16 && key_len != 24 && key_len != 32) { @@ -265,10 +263,10 @@ aes_set_key(void *ctx_arg, const u8 *in_key, unsigned int key_len, u32 *flags) ctx->key_length = key_len; - E_KEY[0] = u32_in (in_key); - E_KEY[1] = u32_in (in_key + 4); - E_KEY[2] = u32_in (in_key + 8); - E_KEY[3] = u32_in (in_key + 12); + E_KEY[0] = le32_to_cpu(key[0]); + E_KEY[1] = le32_to_cpu(key[1]); + E_KEY[2] = le32_to_cpu(key[2]); + E_KEY[3] = le32_to_cpu(key[3]); switch (key_len) { case 16: @@ -278,17 +276,17 @@ aes_set_key(void *ctx_arg, const u8 *in_key, unsigned int key_len, u32 *flags) break; case 24: - E_KEY[4] = u32_in (in_key + 16); - t = E_KEY[5] = u32_in (in_key + 20); + E_KEY[4] = le32_to_cpu(key[4]); + t = E_KEY[5] = le32_to_cpu(key[5]); for (i = 0; i < 8; ++i) loop6 (i); break; case 32: - E_KEY[4] = u32_in (in_key + 16); - E_KEY[5] = u32_in (in_key + 20); - E_KEY[6] = u32_in (in_key + 24); - t = E_KEY[7] = u32_in (in_key + 28); + E_KEY[4] = le32_to_cpu(key[4]); + E_KEY[5] = le32_to_cpu(key[5]); + E_KEY[6] = le32_to_cpu(key[6]); + t = E_KEY[7] = le32_to_cpu(key[7]); for (i = 0; i < 7; ++i) loop8 (i); break; @@ -324,13 +322,15 @@ aes_set_key(void *ctx_arg, const u8 *in_key, unsigned int key_len, u32 *flags) static void aes_encrypt(void *ctx_arg, u8 *out, const u8 *in) { const struct aes_ctx *ctx = ctx_arg; + const __le32 *src = (const __le32 *)in; + __le32 *dst = (__le32 *)out; u32 b0[4], b1[4]; const u32 *kp = E_KEY + 4; - b0[0] = u32_in (in) ^ E_KEY[0]; - b0[1] = u32_in (in + 4) ^ E_KEY[1]; - b0[2] = u32_in (in + 8) ^ E_KEY[2]; - b0[3] = u32_in (in + 12) ^ E_KEY[3]; + b0[0] = le32_to_cpu(src[0]) ^ E_KEY[0]; + b0[1] = le32_to_cpu(src[1]) ^ E_KEY[1]; + b0[2] = le32_to_cpu(src[2]) ^ E_KEY[2]; + b0[3] = le32_to_cpu(src[3]) ^ E_KEY[3]; if (ctx->key_length > 24) { f_nround (b1, b0, kp); @@ -353,10 +353,10 @@ static void aes_encrypt(void *ctx_arg, u8 *out, const u8 *in) f_nround (b1, b0, kp); f_lround (b0, b1, kp); - u32_out (out, b0[0]); - u32_out (out + 4, b0[1]); - u32_out (out + 8, b0[2]); - u32_out (out + 12, b0[3]); + dst[0] = cpu_to_le32(b0[0]); + dst[1] = cpu_to_le32(b0[1]); + dst[2] = cpu_to_le32(b0[2]); + dst[3] = cpu_to_le32(b0[3]); } /* decrypt a block of text */ @@ -377,14 +377,16 @@ static void aes_encrypt(void *ctx_arg, u8 *out, const u8 *in) static void aes_decrypt(void *ctx_arg, u8 *out, const u8 *in) { const struct aes_ctx *ctx = ctx_arg; + const __le32 *src = (const __le32 *)in; + __le32 *dst = (__le32 *)out; u32 b0[4], b1[4]; const int key_len = ctx->key_length; const u32 *kp = D_KEY + key_len + 20; - b0[0] = u32_in (in) ^ E_KEY[key_len + 24]; - b0[1] = u32_in (in + 4) ^ E_KEY[key_len + 25]; - b0[2] = u32_in (in + 8) ^ E_KEY[key_len + 26]; - b0[3] = u32_in (in + 12) ^ E_KEY[key_len + 27]; + b0[0] = le32_to_cpu(src[0]) ^ E_KEY[key_len + 24]; + b0[1] = le32_to_cpu(src[1]) ^ E_KEY[key_len + 25]; + b0[2] = le32_to_cpu(src[2]) ^ E_KEY[key_len + 26]; + b0[3] = le32_to_cpu(src[3]) ^ E_KEY[key_len + 27]; if (key_len > 24) { i_nround (b1, b0, kp); @@ -407,10 +409,10 @@ static void aes_decrypt(void *ctx_arg, u8 *out, const u8 *in) i_nround (b1, b0, kp); i_lround (b0, b1, kp); - u32_out (out, b0[0]); - u32_out (out + 4, b0[1]); - u32_out (out + 8, b0[2]); - u32_out (out + 12, b0[3]); + dst[0] = cpu_to_le32(b0[0]); + dst[1] = cpu_to_le32(b0[1]); + dst[2] = cpu_to_le32(b0[2]); + dst[3] = cpu_to_le32(b0[3]); } diff --git a/crypto/anubis.c b/crypto/anubis.c index 3925eb0..94c4b1f 100644 --- a/crypto/anubis.c +++ b/crypto/anubis.c @@ -32,8 +32,10 @@ #include #include #include +#include #include #include +#include #define ANUBIS_MIN_KEY_SIZE 16 #define ANUBIS_MAX_KEY_SIZE 40 @@ -461,8 +463,8 @@ static const u32 rc[] = { static int anubis_setkey(void *ctx_arg, const u8 *in_key, unsigned int key_len, u32 *flags) { - - int N, R, i, pos, r; + const __be32 *key = (const __be32 *)in_key; + int N, R, i, r; u32 kappa[ANUBIS_MAX_N]; u32 inter[ANUBIS_MAX_N]; @@ -483,13 +485,8 @@ static int anubis_setkey(void *ctx_arg, const u8 *in_key, ctx->R = R = 8 + N; /* * map cipher key to initial key state (mu): */ - for (i = 0, pos = 0; i < N; i++, pos += 4) { - kappa[i] = - (in_key[pos ] << 24) ^ - (in_key[pos + 1] << 16) ^ - (in_key[pos + 2] << 8) ^ - (in_key[pos + 3] ); - } + for (i = 0; i < N; i++) + kappa[i] = be32_to_cpu(key[i]); /* * generate R + 1 round keys: @@ -578,7 +575,9 @@ static int anubis_setkey(void *ctx_arg, const u8 *in_key, static void anubis_crypt(u32 roundKey[ANUBIS_MAX_ROUNDS + 1][4], u8 *ciphertext, const u8 *plaintext, const int R) { - int i, pos, r; + const __be32 *src = (const __be32 *)plaintext; + __be32 *dst = (__be32 *)ciphertext; + int i, r; u32 state[4]; u32 inter[4]; @@ -586,14 +585,8 @@ static void anubis_crypt(u32 roundKey[ANUBIS_MAX_ROUNDS + 1][4], * map plaintext block to cipher state (mu) * and add initial round key (sigma[K^0]): */ - for (i = 0, pos = 0; i < 4; i++, pos += 4) { - state[i] = - (plaintext[pos ] << 24) ^ - (plaintext[pos + 1] << 16) ^ - (plaintext[pos + 2] << 8) ^ - (plaintext[pos + 3] ) ^ - roundKey[0][i]; - } + for (i = 0; i < 4; i++) + state[i] = be32_to_cpu(src[i]) ^ roundKey[0][i]; /* * R - 1 full rounds: @@ -663,13 +656,8 @@ static void anubis_crypt(u32 roundKey[ANUBIS_MAX_ROUNDS + 1][4], * map cipher state to ciphertext block (mu^{-1}): */ - for (i = 0, pos = 0; i < 4; i++, pos += 4) { - u32 w = inter[i]; - ciphertext[pos ] = (u8)(w >> 24); - ciphertext[pos + 1] = (u8)(w >> 16); - ciphertext[pos + 2] = (u8)(w >> 8); - ciphertext[pos + 3] = (u8)(w ); - } + for (i = 0; i < 4; i++) + dst[i] = cpu_to_be32(inter[i]); } static void anubis_encrypt(void *ctx_arg, u8 *dst, const u8 *src) diff --git a/crypto/blowfish.c b/crypto/blowfish.c index a8b29d5..99fc459 100644 --- a/crypto/blowfish.c +++ b/crypto/blowfish.c @@ -19,8 +19,10 @@ #include #include #include +#include #include #include +#include #define BF_BLOCK_SIZE 8 #define BF_MIN_KEY_SIZE 4 diff --git a/crypto/cast5.c b/crypto/cast5.c index bc42f42..282641c 100644 --- a/crypto/cast5.c +++ b/crypto/cast5.c @@ -21,11 +21,13 @@ */ +#include #include #include #include #include #include +#include #define CAST5_BLOCK_SIZE 8 #define CAST5_MIN_KEY_SIZE 5 @@ -578,6 +580,8 @@ static const u32 sb8[256] = { static void cast5_encrypt(void *ctx, u8 * outbuf, const u8 * inbuf) { struct cast5_ctx *c = (struct cast5_ctx *) ctx; + const __be32 *src = (const __be32 *)inbuf; + __be32 *dst = (__be32 *)outbuf; u32 l, r, t; u32 I; /* used by the Fx macros */ u32 *Km; @@ -589,8 +593,8 @@ static void cast5_encrypt(void *ctx, u8 * outbuf, const u8 * inbuf) /* (L0,R0) <-- (m1...m64). (Split the plaintext into left and * right 32-bit halves L0 = m1...m32 and R0 = m33...m64.) */ - l = inbuf[0] << 24 | inbuf[1] << 16 | inbuf[2] << 8 | inbuf[3]; - r = inbuf[4] << 24 | inbuf[5] << 16 | inbuf[6] << 8 | inbuf[7]; + l = be32_to_cpu(src[0]); + r = be32_to_cpu(src[1]); /* (16 rounds) for i from 1 to 16, compute Li and Ri as follows: * Li = Ri-1; @@ -634,19 +638,15 @@ static void cast5_encrypt(void *ctx, u8 * outbuf, const u8 * inbuf) /* c1...c64 <-- (R16,L16). (Exchange final blocks L16, R16 and * concatenate to form the ciphertext.) */ - outbuf[0] = (r >> 24) & 0xff; - outbuf[1] = (r >> 16) & 0xff; - outbuf[2] = (r >> 8) & 0xff; - outbuf[3] = r & 0xff; - outbuf[4] = (l >> 24) & 0xff; - outbuf[5] = (l >> 16) & 0xff; - outbuf[6] = (l >> 8) & 0xff; - outbuf[7] = l & 0xff; + dst[0] = cpu_to_be32(r); + dst[1] = cpu_to_be32(l); } static void cast5_decrypt(void *ctx, u8 * outbuf, const u8 * inbuf) { struct cast5_ctx *c = (struct cast5_ctx *) ctx; + const __be32 *src = (const __be32 *)inbuf; + __be32 *dst = (__be32 *)outbuf; u32 l, r, t; u32 I; u32 *Km; @@ -655,8 +655,8 @@ static void cast5_decrypt(void *ctx, u8 * outbuf, const u8 * inbuf) Km = c->Km; Kr = c->Kr; - l = inbuf[0] << 24 | inbuf[1] << 16 | inbuf[2] << 8 | inbuf[3]; - r = inbuf[4] << 24 | inbuf[5] << 16 | inbuf[6] << 8 | inbuf[7]; + l = be32_to_cpu(src[0]); + r = be32_to_cpu(src[1]); if (!(c->rr)) { t = l; l = r; r = t ^ F1(r, Km[15], Kr[15]); @@ -690,14 +690,8 @@ static void cast5_decrypt(void *ctx, u8 * outbuf, const u8 * inbuf) t = l; l = r; r = t ^ F1(r, Km[0], Kr[0]); } - outbuf[0] = (r >> 24) & 0xff; - outbuf[1] = (r >> 16) & 0xff; - outbuf[2] = (r >> 8) & 0xff; - outbuf[3] = r & 0xff; - outbuf[4] = (l >> 24) & 0xff; - outbuf[5] = (l >> 16) & 0xff; - outbuf[6] = (l >> 8) & 0xff; - outbuf[7] = l & 0xff; + dst[0] = cpu_to_be32(r); + dst[1] = cpu_to_be32(l); } static void key_schedule(u32 * x, u32 * z, u32 * k) @@ -782,7 +776,7 @@ cast5_setkey(void *ctx, const u8 * key, unsigned key_len, u32 * flags) u32 x[4]; u32 z[4]; u32 k[16]; - u8 p_key[16]; + __be32 p_key[4]; struct cast5_ctx *c = (struct cast5_ctx *) ctx; if (key_len < 5 || key_len > 16) { @@ -796,12 +790,10 @@ cast5_setkey(void *ctx, const u8 * key, unsigned key_len, u32 * flags) memcpy(p_key, key, key_len); - x[0] = p_key[0] << 24 | p_key[1] << 16 | p_key[2] << 8 | p_key[3]; - x[1] = p_key[4] << 24 | p_key[5] << 16 | p_key[6] << 8 | p_key[7]; - x[2] = - p_key[8] << 24 | p_key[9] << 16 | p_key[10] << 8 | p_key[11]; - x[3] = - p_key[12] << 24 | p_key[13] << 16 | p_key[14] << 8 | p_key[15]; + x[0] = be32_to_cpu(p_key[0]); + x[1] = be32_to_cpu(p_key[1]); + x[2] = be32_to_cpu(p_key[2]); + x[3] = be32_to_cpu(p_key[3]); key_schedule(x, z, k); for (i = 0; i < 16; i++) diff --git a/crypto/cast6.c b/crypto/cast6.c index 3eb0810..d317fff 100644 --- a/crypto/cast6.c +++ b/crypto/cast6.c @@ -18,11 +18,13 @@ */ +#include #include #include #include #include #include +#include #define CAST6_BLOCK_SIZE 16 #define CAST6_MIN_KEY_SIZE 16 @@ -384,7 +386,7 @@ cast6_setkey(void *ctx, const u8 * in_key, unsigned key_len, u32 * flags) { int i; u32 key[8]; - u8 p_key[32]; /* padded key */ + __be32 p_key[8]; /* padded key */ struct cast6_ctx *c = (struct cast6_ctx *) ctx; if (key_len < 16 || key_len > 32 || key_len % 4 != 0) { @@ -395,14 +397,14 @@ cast6_setkey(void *ctx, const u8 * in_key, unsigned key_len, u32 * flags) memset (p_key, 0, 32); memcpy (p_key, in_key, key_len); - key[0] = p_key[0] << 24 | p_key[1] << 16 | p_key[2] << 8 | p_key[3]; /* A */ - key[1] = p_key[4] << 24 | p_key[5] << 16 | p_key[6] << 8 | p_key[7]; /* B */ - key[2] = p_key[8] << 24 | p_key[9] << 16 | p_key[10] << 8 | p_key[11]; /* C */ - key[3] = p_key[12] << 24 | p_key[13] << 16 | p_key[14] << 8 | p_key[15]; /* D */ - key[4] = p_key[16] << 24 | p_key[17] << 16 | p_key[18] << 8 | p_key[19]; /* E */ - key[5] = p_key[20] << 24 | p_key[21] << 16 | p_key[22] << 8 | p_key[23]; /* F */ - key[6] = p_key[24] << 24 | p_key[25] << 16 | p_key[26] << 8 | p_key[27]; /* G */ - key[7] = p_key[28] << 24 | p_key[29] << 16 | p_key[30] << 8 | p_key[31]; /* H */ + key[0] = be32_to_cpu(p_key[0]); /* A */ + key[1] = be32_to_cpu(p_key[1]); /* B */ + key[2] = be32_to_cpu(p_key[2]); /* C */ + key[3] = be32_to_cpu(p_key[3]); /* D */ + key[4] = be32_to_cpu(p_key[4]); /* E */ + key[5] = be32_to_cpu(p_key[5]); /* F */ + key[6] = be32_to_cpu(p_key[6]); /* G */ + key[7] = be32_to_cpu(p_key[7]); /* H */ @@ -444,14 +446,16 @@ static inline void QBAR (u32 * block, u8 * Kr, u32 * Km) { static void cast6_encrypt (void * ctx, u8 * outbuf, const u8 * inbuf) { struct cast6_ctx * c = (struct cast6_ctx *)ctx; + const __be32 *src = (const __be32 *)inbuf; + __be32 *dst = (__be32 *)outbuf; u32 block[4]; u32 * Km; u8 * Kr; - block[0] = inbuf[0] << 24 | inbuf[1] << 16 | inbuf[2] << 8 | inbuf[3]; - block[1] = inbuf[4] << 24 | inbuf[5] << 16 | inbuf[6] << 8 | inbuf[7]; - block[2] = inbuf[8] << 24 | inbuf[9] << 16 | inbuf[10] << 8 | inbuf[11]; - block[3] = inbuf[12] << 24 | inbuf[13] << 16 | inbuf[14] << 8 | inbuf[15]; + block[0] = be32_to_cpu(src[0]); + block[1] = be32_to_cpu(src[1]); + block[2] = be32_to_cpu(src[2]); + block[3] = be32_to_cpu(src[3]); Km = c->Km[0]; Kr = c->Kr[0]; Q (block, Kr, Km); Km = c->Km[1]; Kr = c->Kr[1]; Q (block, Kr, Km); @@ -465,35 +469,25 @@ static void cast6_encrypt (void * ctx, u8 * outbuf, const u8 * inbuf) { Km = c->Km[9]; Kr = c->Kr[9]; QBAR (block, Kr, Km); Km = c->Km[10]; Kr = c->Kr[10]; QBAR (block, Kr, Km); Km = c->Km[11]; Kr = c->Kr[11]; QBAR (block, Kr, Km); - - outbuf[0] = (block[0] >> 24) & 0xff; - outbuf[1] = (block[0] >> 16) & 0xff; - outbuf[2] = (block[0] >> 8) & 0xff; - outbuf[3] = block[0] & 0xff; - outbuf[4] = (block[1] >> 24) & 0xff; - outbuf[5] = (block[1] >> 16) & 0xff; - outbuf[6] = (block[1] >> 8) & 0xff; - outbuf[7] = block[1] & 0xff; - outbuf[8] = (block[2] >> 24) & 0xff; - outbuf[9] = (block[2] >> 16) & 0xff; - outbuf[10] = (block[2] >> 8) & 0xff; - outbuf[11] = block[2] & 0xff; - outbuf[12] = (block[3] >> 24) & 0xff; - outbuf[13] = (block[3] >> 16) & 0xff; - outbuf[14] = (block[3] >> 8) & 0xff; - outbuf[15] = block[3] & 0xff; + + dst[0] = cpu_to_be32(block[0]); + dst[1] = cpu_to_be32(block[1]); + dst[2] = cpu_to_be32(block[2]); + dst[3] = cpu_to_be32(block[3]); } static void cast6_decrypt (void * ctx, u8 * outbuf, const u8 * inbuf) { struct cast6_ctx * c = (struct cast6_ctx *)ctx; + const __be32 *src = (const __be32 *)inbuf; + __be32 *dst = (__be32 *)outbuf; u32 block[4]; u32 * Km; u8 * Kr; - block[0] = inbuf[0] << 24 | inbuf[1] << 16 | inbuf[2] << 8 | inbuf[3]; - block[1] = inbuf[4] << 24 | inbuf[5] << 16 | inbuf[6] << 8 | inbuf[7]; - block[2] = inbuf[8] << 24 | inbuf[9] << 16 | inbuf[10] << 8 | inbuf[11]; - block[3] = inbuf[12] << 24 | inbuf[13] << 16 | inbuf[14] << 8 | inbuf[15]; + block[0] = be32_to_cpu(src[0]); + block[1] = be32_to_cpu(src[1]); + block[2] = be32_to_cpu(src[2]); + block[3] = be32_to_cpu(src[3]); Km = c->Km[11]; Kr = c->Kr[11]; Q (block, Kr, Km); Km = c->Km[10]; Kr = c->Kr[10]; Q (block, Kr, Km); @@ -508,22 +502,10 @@ static void cast6_decrypt (void * ctx, u8 * outbuf, const u8 * inbuf) { Km = c->Km[1]; Kr = c->Kr[1]; QBAR (block, Kr, Km); Km = c->Km[0]; Kr = c->Kr[0]; QBAR (block, Kr, Km); - outbuf[0] = (block[0] >> 24) & 0xff; - outbuf[1] = (block[0] >> 16) & 0xff; - outbuf[2] = (block[0] >> 8) & 0xff; - outbuf[3] = block[0] & 0xff; - outbuf[4] = (block[1] >> 24) & 0xff; - outbuf[5] = (block[1] >> 16) & 0xff; - outbuf[6] = (block[1] >> 8) & 0xff; - outbuf[7] = block[1] & 0xff; - outbuf[8] = (block[2] >> 24) & 0xff; - outbuf[9] = (block[2] >> 16) & 0xff; - outbuf[10] = (block[2] >> 8) & 0xff; - outbuf[11] = block[2] & 0xff; - outbuf[12] = (block[3] >> 24) & 0xff; - outbuf[13] = (block[3] >> 16) & 0xff; - outbuf[14] = (block[3] >> 8) & 0xff; - outbuf[15] = block[3] & 0xff; + dst[0] = cpu_to_be32(block[0]); + dst[1] = cpu_to_be32(block[1]); + dst[2] = cpu_to_be32(block[2]); + dst[3] = cpu_to_be32(block[3]); } static struct crypto_alg alg = { diff --git a/crypto/crc32c.c b/crypto/crc32c.c index 256956c..9533624 100644 --- a/crypto/crc32c.c +++ b/crypto/crc32c.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #define CHKSUM_BLOCK_SIZE 32 diff --git a/crypto/des.c b/crypto/des.c index a3c863d..dae4298 100644 --- a/crypto/des.c +++ b/crypto/des.c @@ -12,11 +12,13 @@ * */ +#include #include #include #include #include #include +#include #define DES_KEY_SIZE 8 #define DES_EXPKEY_WORDS 32 diff --git a/crypto/khazad.c b/crypto/khazad.c index 738cb0d..6809210 100644 --- a/crypto/khazad.c +++ b/crypto/khazad.c @@ -22,8 +22,10 @@ #include #include #include +#include #include #include +#include #define KHAZAD_KEY_SIZE 16 #define KHAZAD_BLOCK_SIZE 8 @@ -755,8 +757,8 @@ static const u64 c[KHAZAD_ROUNDS + 1] = { static int khazad_setkey(void *ctx_arg, const u8 *in_key, unsigned int key_len, u32 *flags) { - struct khazad_ctx *ctx = ctx_arg; + const __be64 *key = (const __be64 *)in_key; int r; const u64 *S = T7; u64 K2, K1; @@ -767,22 +769,8 @@ static int khazad_setkey(void *ctx_arg, const u8 *in_key, return -EINVAL; } - K2 = ((u64)in_key[ 0] << 56) ^ - ((u64)in_key[ 1] << 48) ^ - ((u64)in_key[ 2] << 40) ^ - ((u64)in_key[ 3] << 32) ^ - ((u64)in_key[ 4] << 24) ^ - ((u64)in_key[ 5] << 16) ^ - ((u64)in_key[ 6] << 8) ^ - ((u64)in_key[ 7] ); - K1 = ((u64)in_key[ 8] << 56) ^ - ((u64)in_key[ 9] << 48) ^ - ((u64)in_key[10] << 40) ^ - ((u64)in_key[11] << 32) ^ - ((u64)in_key[12] << 24) ^ - ((u64)in_key[13] << 16) ^ - ((u64)in_key[14] << 8) ^ - ((u64)in_key[15] ); + K2 = be64_to_cpu(key[0]); + K1 = be64_to_cpu(key[1]); /* setup the encrypt key */ for (r = 0; r <= KHAZAD_ROUNDS; r++) { @@ -820,19 +808,12 @@ static int khazad_setkey(void *ctx_arg, const u8 *in_key, static void khazad_crypt(const u64 roundKey[KHAZAD_ROUNDS + 1], u8 *ciphertext, const u8 *plaintext) { - + const __be64 *src = (const __be64 *)plaintext; + __be64 *dst = (__be64 *)ciphertext; int r; u64 state; - state = ((u64)plaintext[0] << 56) ^ - ((u64)plaintext[1] << 48) ^ - ((u64)plaintext[2] << 40) ^ - ((u64)plaintext[3] << 32) ^ - ((u64)plaintext[4] << 24) ^ - ((u64)plaintext[5] << 16) ^ - ((u64)plaintext[6] << 8) ^ - ((u64)plaintext[7] ) ^ - roundKey[0]; + state = be64_to_cpu(*src) ^ roundKey[0]; for (r = 1; r < KHAZAD_ROUNDS; r++) { state = T0[(int)(state >> 56) ] ^ @@ -856,15 +837,7 @@ static void khazad_crypt(const u64 roundKey[KHAZAD_ROUNDS + 1], (T7[(int)(state ) & 0xff] & 0x00000000000000ffULL) ^ roundKey[KHAZAD_ROUNDS]; - ciphertext[0] = (u8)(state >> 56); - ciphertext[1] = (u8)(state >> 48); - ciphertext[2] = (u8)(state >> 40); - ciphertext[3] = (u8)(state >> 32); - ciphertext[4] = (u8)(state >> 24); - ciphertext[5] = (u8)(state >> 16); - ciphertext[6] = (u8)(state >> 8); - ciphertext[7] = (u8)(state ); - + *dst = cpu_to_be64(state); } static void khazad_encrypt(void *ctx_arg, u8 *dst, const u8 *src) diff --git a/crypto/md4.c b/crypto/md4.c index bef6a9e..a2d6df5 100644 --- a/crypto/md4.c +++ b/crypto/md4.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #define MD4_DIGEST_SIZE 16 diff --git a/crypto/md5.c b/crypto/md5.c index 1ed45f9..7f041ae 100644 --- a/crypto/md5.c +++ b/crypto/md5.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #define MD5_DIGEST_SIZE 16 diff --git a/crypto/michael_mic.c b/crypto/michael_mic.c index a470bcb..4f6ab23 100644 --- a/crypto/michael_mic.c +++ b/crypto/michael_mic.c @@ -10,10 +10,12 @@ * published by the Free Software Foundation. */ +#include #include #include #include #include +#include struct michael_mic_ctx { @@ -43,21 +45,6 @@ do { \ } while (0) -static inline u32 get_le32(const u8 *p) -{ - return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24); -} - - -static inline void put_le32(u8 *p, u32 v) -{ - p[0] = v; - p[1] = v >> 8; - p[2] = v >> 16; - p[3] = v >> 24; -} - - static void michael_init(void *ctx) { struct michael_mic_ctx *mctx = ctx; @@ -68,6 +55,7 @@ static void michael_init(void *ctx) static void michael_update(void *ctx, const u8 *data, unsigned int len) { struct michael_mic_ctx *mctx = ctx; + const __le32 *src; if (mctx->pending_len) { int flen = 4 - mctx->pending_len; @@ -81,21 +69,23 @@ static void michael_update(void *ctx, const u8 *data, unsigned int len) if (mctx->pending_len < 4) return; - mctx->l ^= get_le32(mctx->pending); + src = (const __le32 *)mctx->pending; + mctx->l ^= le32_to_cpup(src); michael_block(mctx->l, mctx->r); mctx->pending_len = 0; } + src = (const __le32 *)data; + while (len >= 4) { - mctx->l ^= get_le32(data); + mctx->l ^= le32_to_cpup(src++); michael_block(mctx->l, mctx->r); - data += 4; len -= 4; } if (len > 0) { mctx->pending_len = len; - memcpy(mctx->pending, data, len); + memcpy(mctx->pending, src, len); } } @@ -104,6 +94,7 @@ static void michael_final(void *ctx, u8 *out) { struct michael_mic_ctx *mctx = ctx; u8 *data = mctx->pending; + __le32 *dst = (__le32 *)out; /* Last block and padding (0x5a, 4..7 x 0) */ switch (mctx->pending_len) { @@ -125,8 +116,8 @@ static void michael_final(void *ctx, u8 *out) /* l ^= 0; */ michael_block(mctx->l, mctx->r); - put_le32(out, mctx->l); - put_le32(out + 4, mctx->r); + dst[0] = cpu_to_le32(mctx->l); + dst[1] = cpu_to_le32(mctx->r); } @@ -134,13 +125,16 @@ static int michael_setkey(void *ctx, const u8 *key, unsigned int keylen, u32 *flags) { struct michael_mic_ctx *mctx = ctx; + const __le32 *data = (const __le32 *)key; + if (keylen != 8) { if (flags) *flags = CRYPTO_TFM_RES_BAD_KEY_LEN; return -EINVAL; } - mctx->l = get_le32(key); - mctx->r = get_le32(key + 4); + + mctx->l = le32_to_cpu(data[0]); + mctx->r = le32_to_cpu(data[1]); return 0; } diff --git a/crypto/serpent.c b/crypto/serpent.c index 3cf2c50..a950ff8 100644 --- a/crypto/serpent.c +++ b/crypto/serpent.c @@ -20,6 +20,7 @@ #include #include #include +#include /* Key is padded to the maximum of 256 bits before round key generation. * Any key length <= 256 bits (32 bytes) is allowed by the algorithm. diff --git a/crypto/sha1.c b/crypto/sha1.c index 4016f3b..c686e78 100644 --- a/crypto/sha1.c +++ b/crypto/sha1.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -72,20 +73,12 @@ static void sha1_update(void *ctx, const u8 *data, unsigned int len) static void sha1_final(void* ctx, u8 *out) { struct sha1_ctx *sctx = ctx; - u32 i, j, index, padlen; - u64 t; - u8 bits[8] = { 0, }; + __be32 *dst = (__be32 *)out; + u32 i, index, padlen; + __be64 bits; static const u8 padding[64] = { 0x80, }; - t = sctx->count; - bits[7] = 0xff & t; t>>=8; - bits[6] = 0xff & t; t>>=8; - bits[5] = 0xff & t; t>>=8; - bits[4] = 0xff & t; t>>=8; - bits[3] = 0xff & t; t>>=8; - bits[2] = 0xff & t; t>>=8; - bits[1] = 0xff & t; t>>=8; - bits[0] = 0xff & t; + bits = cpu_to_be64(sctx->count); /* Pad out to 56 mod 64 */ index = (sctx->count >> 3) & 0x3f; @@ -93,16 +86,11 @@ static void sha1_final(void* ctx, u8 *out) sha1_update(sctx, padding, padlen); /* Append length */ - sha1_update(sctx, bits, sizeof bits); + sha1_update(sctx, (const u8 *)&bits, sizeof(bits)); /* Store state in digest */ - for (i = j = 0; i < 5; i++, j += 4) { - u32 t2 = sctx->state[i]; - out[j+3] = t2 & 0xff; t2>>=8; - out[j+2] = t2 & 0xff; t2>>=8; - out[j+1] = t2 & 0xff; t2>>=8; - out[j ] = t2 & 0xff; - } + for (i = 0; i < 5; i++) + dst[i] = cpu_to_be32(sctx->state[i]); /* Wipe context */ memset(sctx, 0, sizeof *sctx); diff --git a/crypto/sha256.c b/crypto/sha256.c index c78da50..9d5ef67 100644 --- a/crypto/sha256.c +++ b/crypto/sha256.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -279,22 +280,15 @@ static void sha256_update(void *ctx, const u8 *data, unsigned int len) static void sha256_final(void* ctx, u8 *out) { struct sha256_ctx *sctx = ctx; - u8 bits[8]; - unsigned int index, pad_len, t; - int i, j; + __be32 *dst = (__be32 *)out; + __be32 bits[2]; + unsigned int index, pad_len; + int i; static const u8 padding[64] = { 0x80, }; /* Save number of bits */ - t = sctx->count[0]; - bits[7] = t; t >>= 8; - bits[6] = t; t >>= 8; - bits[5] = t; t >>= 8; - bits[4] = t; - t = sctx->count[1]; - bits[3] = t; t >>= 8; - bits[2] = t; t >>= 8; - bits[1] = t; t >>= 8; - bits[0] = t; + bits[1] = cpu_to_be32(sctx->count[0]); + bits[0] = cpu_to_be32(sctx->count[1]); /* Pad out to 56 mod 64. */ index = (sctx->count[0] >> 3) & 0x3f; @@ -302,16 +296,11 @@ static void sha256_final(void* ctx, u8 *out) sha256_update(sctx, padding, pad_len); /* Append length (before padding) */ - sha256_update(sctx, bits, 8); + sha256_update(sctx, (const u8 *)bits, sizeof(bits)); /* Store state in digest */ - for (i = j = 0; i < 8; i++, j += 4) { - t = sctx->state[i]; - out[j+3] = t; t >>= 8; - out[j+2] = t; t >>= 8; - out[j+1] = t; t >>= 8; - out[j ] = t; - } + for (i = 0; i < 8; i++) + dst[i] = cpu_to_be32(sctx->state[i]); /* Zeroize sensitive information. */ memset(sctx, 0, sizeof(*sctx)); diff --git a/crypto/sha512.c b/crypto/sha512.c index c663438..3e6e939 100644 --- a/crypto/sha512.c +++ b/crypto/sha512.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -235,39 +236,17 @@ static void sha512_final(void *ctx, u8 *hash) { struct sha512_ctx *sctx = ctx; - static u8 padding[128] = { 0x80, }; - - u32 t; - u64 t2; - u8 bits[128]; + __be64 *dst = (__be64 *)hash; + __be32 bits[4]; unsigned int index, pad_len; - int i, j; - - index = pad_len = t = i = j = 0; - t2 = 0; + int i; /* Save number of bits */ - t = sctx->count[0]; - bits[15] = t; t>>=8; - bits[14] = t; t>>=8; - bits[13] = t; t>>=8; - bits[12] = t; - t = sctx->count[1]; - bits[11] = t; t>>=8; - bits[10] = t; t>>=8; - bits[9 ] = t; t>>=8; - bits[8 ] = t; - t = sctx->count[2]; - bits[7 ] = t; t>>=8; - bits[6 ] = t; t>>=8; - bits[5 ] = t; t>>=8; - bits[4 ] = t; - t = sctx->count[3]; - bits[3 ] = t; t>>=8; - bits[2 ] = t; t>>=8; - bits[1 ] = t; t>>=8; - bits[0 ] = t; + bits[3] = cpu_to_be32(sctx->count[0]); + bits[2] = cpu_to_be32(sctx->count[1]); + bits[1] = cpu_to_be32(sctx->count[2]); + bits[0] = cpu_to_be32(sctx->count[3]); /* Pad out to 112 mod 128. */ index = (sctx->count[0] >> 3) & 0x7f; @@ -275,21 +254,12 @@ sha512_final(void *ctx, u8 *hash) sha512_update(sctx, padding, pad_len); /* Append length (before padding) */ - sha512_update(sctx, bits, 16); + sha512_update(sctx, (const u8 *)bits, sizeof(bits)); /* Store state in digest */ - for (i = j = 0; i < 8; i++, j += 8) { - t2 = sctx->state[i]; - hash[j+7] = (char)t2 & 0xff; t2>>=8; - hash[j+6] = (char)t2 & 0xff; t2>>=8; - hash[j+5] = (char)t2 & 0xff; t2>>=8; - hash[j+4] = (char)t2 & 0xff; t2>>=8; - hash[j+3] = (char)t2 & 0xff; t2>>=8; - hash[j+2] = (char)t2 & 0xff; t2>>=8; - hash[j+1] = (char)t2 & 0xff; t2>>=8; - hash[j ] = (char)t2 & 0xff; - } - + for (i = 0; i < 8; i++) + dst[i] = cpu_to_be64(sctx->state[i]); + /* Zeroize sensitive information. */ memset(sctx, 0, sizeof(struct sha512_ctx)); } diff --git a/crypto/tea.c b/crypto/tea.c index 5924efd..e0077c7 100644 --- a/crypto/tea.c +++ b/crypto/tea.c @@ -22,8 +22,10 @@ #include #include #include +#include #include #include +#include #define TEA_KEY_SIZE 16 #define TEA_BLOCK_SIZE 8 @@ -35,9 +37,6 @@ #define XTEA_ROUNDS 32 #define XTEA_DELTA 0x9e3779b9 -#define u32_in(x) le32_to_cpu(*(const __le32 *)(x)) -#define u32_out(to, from) (*(__le32 *)(to) = cpu_to_le32(from)) - struct tea_ctx { u32 KEY[4]; }; @@ -49,8 +48,8 @@ struct xtea_ctx { static int tea_setkey(void *ctx_arg, const u8 *in_key, unsigned int key_len, u32 *flags) { - struct tea_ctx *ctx = ctx_arg; + const __le32 *key = (const __le32 *)in_key; if (key_len != 16) { @@ -58,10 +57,10 @@ static int tea_setkey(void *ctx_arg, const u8 *in_key, return -EINVAL; } - ctx->KEY[0] = u32_in (in_key); - ctx->KEY[1] = u32_in (in_key + 4); - ctx->KEY[2] = u32_in (in_key + 8); - ctx->KEY[3] = u32_in (in_key + 12); + ctx->KEY[0] = le32_to_cpu(key[0]); + ctx->KEY[1] = le32_to_cpu(key[1]); + ctx->KEY[2] = le32_to_cpu(key[2]); + ctx->KEY[3] = le32_to_cpu(key[3]); return 0; @@ -73,9 +72,11 @@ static void tea_encrypt(void *ctx_arg, u8 *dst, const u8 *src) u32 k0, k1, k2, k3; struct tea_ctx *ctx = ctx_arg; + const __le32 *in = (const __le32 *)src; + __le32 *out = (__le32 *)dst; - y = u32_in (src); - z = u32_in (src + 4); + y = le32_to_cpu(in[0]); + z = le32_to_cpu(in[1]); k0 = ctx->KEY[0]; k1 = ctx->KEY[1]; @@ -90,19 +91,20 @@ static void tea_encrypt(void *ctx_arg, u8 *dst, const u8 *src) z += ((y << 4) + k2) ^ (y + sum) ^ ((y >> 5) + k3); } - u32_out (dst, y); - u32_out (dst + 4, z); + out[0] = cpu_to_le32(y); + out[1] = cpu_to_le32(z); } static void tea_decrypt(void *ctx_arg, u8 *dst, const u8 *src) { u32 y, z, n, sum; u32 k0, k1, k2, k3; - struct tea_ctx *ctx = ctx_arg; + const __le32 *in = (const __le32 *)src; + __le32 *out = (__le32 *)dst; - y = u32_in (src); - z = u32_in (src + 4); + y = le32_to_cpu(in[0]); + z = le32_to_cpu(in[1]); k0 = ctx->KEY[0]; k1 = ctx->KEY[1]; @@ -119,16 +121,15 @@ static void tea_decrypt(void *ctx_arg, u8 *dst, const u8 *src) sum -= TEA_DELTA; } - u32_out (dst, y); - u32_out (dst + 4, z); - + out[0] = cpu_to_le32(y); + out[1] = cpu_to_le32(z); } static int xtea_setkey(void *ctx_arg, const u8 *in_key, unsigned int key_len, u32 *flags) { - struct xtea_ctx *ctx = ctx_arg; + const __le32 *key = (const __le32 *)in_key; if (key_len != 16) { @@ -136,10 +137,10 @@ static int xtea_setkey(void *ctx_arg, const u8 *in_key, return -EINVAL; } - ctx->KEY[0] = u32_in (in_key); - ctx->KEY[1] = u32_in (in_key + 4); - ctx->KEY[2] = u32_in (in_key + 8); - ctx->KEY[3] = u32_in (in_key + 12); + ctx->KEY[0] = le32_to_cpu(key[0]); + ctx->KEY[1] = le32_to_cpu(key[1]); + ctx->KEY[2] = le32_to_cpu(key[2]); + ctx->KEY[3] = le32_to_cpu(key[3]); return 0; @@ -147,14 +148,15 @@ static int xtea_setkey(void *ctx_arg, const u8 *in_key, static void xtea_encrypt(void *ctx_arg, u8 *dst, const u8 *src) { - u32 y, z, sum = 0; u32 limit = XTEA_DELTA * XTEA_ROUNDS; struct xtea_ctx *ctx = ctx_arg; + const __le32 *in = (const __le32 *)src; + __le32 *out = (__le32 *)dst; - y = u32_in (src); - z = u32_in (src + 4); + y = le32_to_cpu(in[0]); + z = le32_to_cpu(in[1]); while (sum != limit) { y += ((z << 4 ^ z >> 5) + z) ^ (sum + ctx->KEY[sum&3]); @@ -162,19 +164,19 @@ static void xtea_encrypt(void *ctx_arg, u8 *dst, const u8 *src) z += ((y << 4 ^ y >> 5) + y) ^ (sum + ctx->KEY[sum>>11 &3]); } - u32_out (dst, y); - u32_out (dst + 4, z); - + out[0] = cpu_to_le32(y); + out[1] = cpu_to_le32(z); } static void xtea_decrypt(void *ctx_arg, u8 *dst, const u8 *src) { - u32 y, z, sum; struct tea_ctx *ctx = ctx_arg; + const __le32 *in = (const __le32 *)src; + __le32 *out = (__le32 *)dst; - y = u32_in (src); - z = u32_in (src + 4); + y = le32_to_cpu(in[0]); + z = le32_to_cpu(in[1]); sum = XTEA_DELTA * XTEA_ROUNDS; @@ -184,22 +186,22 @@ static void xtea_decrypt(void *ctx_arg, u8 *dst, const u8 *src) y -= ((z << 4 ^ z >> 5) + z) ^ (sum + ctx->KEY[sum & 3]); } - u32_out (dst, y); - u32_out (dst + 4, z); - + out[0] = cpu_to_le32(y); + out[1] = cpu_to_le32(z); } static void xeta_encrypt(void *ctx_arg, u8 *dst, const u8 *src) { - u32 y, z, sum = 0; u32 limit = XTEA_DELTA * XTEA_ROUNDS; struct xtea_ctx *ctx = ctx_arg; + const __le32 *in = (const __le32 *)src; + __le32 *out = (__le32 *)dst; - y = u32_in (src); - z = u32_in (src + 4); + y = le32_to_cpu(in[0]); + z = le32_to_cpu(in[1]); while (sum != limit) { y += (z << 4 ^ z >> 5) + (z ^ sum) + ctx->KEY[sum&3]; @@ -207,19 +209,19 @@ static void xeta_encrypt(void *ctx_arg, u8 *dst, const u8 *src) z += (y << 4 ^ y >> 5) + (y ^ sum) + ctx->KEY[sum>>11 &3]; } - u32_out (dst, y); - u32_out (dst + 4, z); - + out[0] = cpu_to_le32(y); + out[1] = cpu_to_le32(z); } static void xeta_decrypt(void *ctx_arg, u8 *dst, const u8 *src) { - u32 y, z, sum; struct tea_ctx *ctx = ctx_arg; + const __le32 *in = (const __le32 *)src; + __le32 *out = (__le32 *)dst; - y = u32_in (src); - z = u32_in (src + 4); + y = le32_to_cpu(in[0]); + z = le32_to_cpu(in[1]); sum = XTEA_DELTA * XTEA_ROUNDS; @@ -229,9 +231,8 @@ static void xeta_decrypt(void *ctx_arg, u8 *dst, const u8 *src) y -= (z << 4 ^ z >> 5) + (z ^ sum) + ctx->KEY[sum & 3]; } - u32_out (dst, y); - u32_out (dst + 4, z); - + out[0] = cpu_to_le32(y); + out[1] = cpu_to_le32(z); } static struct crypto_alg tea_alg = { diff --git a/crypto/tgr192.c b/crypto/tgr192.c index f0a45cf..2d8e44f 100644 --- a/crypto/tgr192.c +++ b/crypto/tgr192.c @@ -24,8 +24,10 @@ #include #include #include +#include #include #include +#include #define TGR192_DIGEST_SIZE 24 #define TGR160_DIGEST_SIZE 20 @@ -467,18 +469,10 @@ static void tgr192_transform(struct tgr192_ctx *tctx, const u8 * data) u64 a, b, c, aa, bb, cc; u64 x[8]; int i; - const u8 *ptr = data; - - for (i = 0; i < 8; i++, ptr += 8) { - x[i] = (((u64)ptr[7] ) << 56) ^ - (((u64)ptr[6] & 0xffL) << 48) ^ - (((u64)ptr[5] & 0xffL) << 40) ^ - (((u64)ptr[4] & 0xffL) << 32) ^ - (((u64)ptr[3] & 0xffL) << 24) ^ - (((u64)ptr[2] & 0xffL) << 16) ^ - (((u64)ptr[1] & 0xffL) << 8) ^ - (((u64)ptr[0] & 0xffL) ); - } + const __le64 *ptr = (const __le64 *)data; + + for (i = 0; i < 8; i++) + x[i] = le64_to_cpu(ptr[i]); /* save */ a = aa = tctx->a; @@ -558,9 +552,10 @@ static void tgr192_update(void *ctx, const u8 * inbuf, unsigned int len) static void tgr192_final(void *ctx, u8 * out) { struct tgr192_ctx *tctx = ctx; + __be64 *dst = (__be64 *)out; + __be64 *be64p; + __le32 *le32p; u32 t, msb, lsb; - u8 *p; - int i, j; tgr192_update(tctx, NULL, 0); /* flush */ ; @@ -594,41 +589,16 @@ static void tgr192_final(void *ctx, u8 * out) memset(tctx->hash, 0, 56); /* fill next block with zeroes */ } /* append the 64 bit count */ - tctx->hash[56] = lsb; - tctx->hash[57] = lsb >> 8; - tctx->hash[58] = lsb >> 16; - tctx->hash[59] = lsb >> 24; - tctx->hash[60] = msb; - tctx->hash[61] = msb >> 8; - tctx->hash[62] = msb >> 16; - tctx->hash[63] = msb >> 24; + le32p = (__le32 *)&tctx->hash[56]; + le32p[0] = cpu_to_le32(lsb); + le32p[1] = cpu_to_le32(msb); + tgr192_transform(tctx, tctx->hash); - p = tctx->hash; - *p++ = tctx->a >> 56; *p++ = tctx->a >> 48; *p++ = tctx->a >> 40; - *p++ = tctx->a >> 32; *p++ = tctx->a >> 24; *p++ = tctx->a >> 16; - *p++ = tctx->a >> 8; *p++ = tctx->a;\ - *p++ = tctx->b >> 56; *p++ = tctx->b >> 48; *p++ = tctx->b >> 40; - *p++ = tctx->b >> 32; *p++ = tctx->b >> 24; *p++ = tctx->b >> 16; - *p++ = tctx->b >> 8; *p++ = tctx->b; - *p++ = tctx->c >> 56; *p++ = tctx->c >> 48; *p++ = tctx->c >> 40; - *p++ = tctx->c >> 32; *p++ = tctx->c >> 24; *p++ = tctx->c >> 16; - *p++ = tctx->c >> 8; *p++ = tctx->c; - - - /* unpack the hash */ - j = 7; - for (i = 0; i < 8; i++) { - out[j--] = (tctx->a >> 8 * i) & 0xff; - } - j = 15; - for (i = 0; i < 8; i++) { - out[j--] = (tctx->b >> 8 * i) & 0xff; - } - j = 23; - for (i = 0; i < 8; i++) { - out[j--] = (tctx->c >> 8 * i) & 0xff; - } + be64p = (__be64 *)tctx->hash; + dst[0] = be64p[0] = cpu_to_be64(tctx->a); + dst[1] = be64p[1] = cpu_to_be64(tctx->b); + dst[2] = be64p[2] = cpu_to_be64(tctx->c); } static void tgr160_final(void *ctx, u8 * out) diff --git a/crypto/twofish.c b/crypto/twofish.c index 4efff8c..b501d5a 100644 --- a/crypto/twofish.c +++ b/crypto/twofish.c @@ -37,6 +37,8 @@ * Abstract Algebra_ by Joseph A. Gallian, especially chapter 22 in the * Third Edition. */ + +#include #include #include #include @@ -621,13 +623,11 @@ static const u8 calc_sb_tbl[512] = { * whitening subkey number m. */ #define INPACK(n, x, m) \ - x = in[4 * (n)] ^ (in[4 * (n) + 1] << 8) \ - ^ (in[4 * (n) + 2] << 16) ^ (in[4 * (n) + 3] << 24) ^ ctx->w[m] + x = le32_to_cpu(src[n]) ^ ctx->w[m] #define OUTUNPACK(n, x, m) \ x ^= ctx->w[m]; \ - out[4 * (n)] = x; out[4 * (n) + 1] = x >> 8; \ - out[4 * (n) + 2] = x >> 16; out[4 * (n) + 3] = x >> 24 + dst[n] = cpu_to_le32(x) #define TF_MIN_KEY_SIZE 16 #define TF_MAX_KEY_SIZE 32 @@ -804,6 +804,8 @@ static int twofish_setkey(void *cx, const u8 *key, static void twofish_encrypt(void *cx, u8 *out, const u8 *in) { struct twofish_ctx *ctx = cx; + const __le32 *src = (const __le32 *)in; + __le32 *dst = (__le32 *)out; /* The four 32-bit chunks of the text. */ u32 a, b, c, d; @@ -839,6 +841,8 @@ static void twofish_encrypt(void *cx, u8 *out, const u8 *in) static void twofish_decrypt(void *cx, u8 *out, const u8 *in) { struct twofish_ctx *ctx = cx; + const __le32 *src = (const __le32 *)in; + __le32 *dst = (__le32 *)out; /* The four 32-bit chunks of the text. */ u32 a, b, c, d; diff --git a/crypto/wp512.c b/crypto/wp512.c index fd6e20e..b226a12 100644 --- a/crypto/wp512.c +++ b/crypto/wp512.c @@ -22,8 +22,10 @@ #include #include #include +#include #include #include +#include #define WP512_DIGEST_SIZE 64 #define WP384_DIGEST_SIZE 48 @@ -778,19 +780,10 @@ static void wp512_process_buffer(struct wp512_ctx *wctx) { u64 block[8]; /* mu(buffer) */ u64 state[8]; /* the cipher state */ u64 L[8]; - u8 *buffer = wctx->buffer; + const __be64 *buffer = (const __be64 *)wctx->buffer; - for (i = 0; i < 8; i++, buffer += 8) { - block[i] = - (((u64)buffer[0] ) << 56) ^ - (((u64)buffer[1] & 0xffL) << 48) ^ - (((u64)buffer[2] & 0xffL) << 40) ^ - (((u64)buffer[3] & 0xffL) << 32) ^ - (((u64)buffer[4] & 0xffL) << 24) ^ - (((u64)buffer[5] & 0xffL) << 16) ^ - (((u64)buffer[6] & 0xffL) << 8) ^ - (((u64)buffer[7] & 0xffL) ); - } + for (i = 0; i < 8; i++) + block[i] = be64_to_cpu(buffer[i]); state[0] = block[0] ^ (K[0] = wctx->hash[0]); state[1] = block[1] ^ (K[1] = wctx->hash[1]); @@ -1069,7 +1062,7 @@ static void wp512_final(void *ctx, u8 *out) u8 *bitLength = wctx->bitLength; int bufferBits = wctx->bufferBits; int bufferPos = wctx->bufferPos; - u8 *digest = out; + __be64 *digest = (__be64 *)out; buffer[bufferPos] |= 0x80U >> (bufferBits & 7); bufferPos++; @@ -1088,17 +1081,8 @@ static void wp512_final(void *ctx, u8 *out) memcpy(&buffer[WP512_BLOCK_SIZE - WP512_LENGTHBYTES], bitLength, WP512_LENGTHBYTES); wp512_process_buffer(wctx); - for (i = 0; i < WP512_DIGEST_SIZE/8; i++) { - digest[0] = (u8)(wctx->hash[i] >> 56); - digest[1] = (u8)(wctx->hash[i] >> 48); - digest[2] = (u8)(wctx->hash[i] >> 40); - digest[3] = (u8)(wctx->hash[i] >> 32); - digest[4] = (u8)(wctx->hash[i] >> 24); - digest[5] = (u8)(wctx->hash[i] >> 16); - digest[6] = (u8)(wctx->hash[i] >> 8); - digest[7] = (u8)(wctx->hash[i] ); - digest += 8; - } + for (i = 0; i < WP512_DIGEST_SIZE/8; i++) + digest[i] = cpu_to_be64(wctx->hash[i]); wctx->bufferBits = bufferBits; wctx->bufferPos = bufferPos; } diff --git a/drivers/crypto/padlock-aes.c b/drivers/crypto/padlock-aes.c index 71407c5..963e03d 100644 --- a/drivers/crypto/padlock-aes.c +++ b/drivers/crypto/padlock-aes.c @@ -99,9 +99,6 @@ byte(const uint32_t x, const unsigned n) return x >> (n << 3); } -#define uint32_t_in(x) le32_to_cpu(*(const uint32_t *)(x)) -#define uint32_t_out(to, from) (*(uint32_t *)(to) = cpu_to_le32(from)) - #define E_KEY ctx->E #define D_KEY ctx->D @@ -294,6 +291,7 @@ static int aes_set_key(void *ctx_arg, const uint8_t *in_key, unsigned int key_len, uint32_t *flags) { struct aes_ctx *ctx = aes_ctx(ctx_arg); + const __le32 *key = (const __le32 *)in_key; uint32_t i, t, u, v, w; uint32_t P[AES_EXTENDED_KEY_SIZE]; uint32_t rounds; @@ -313,10 +311,10 @@ aes_set_key(void *ctx_arg, const uint8_t *in_key, unsigned int key_len, uint32_t ctx->E = ctx->e_data; ctx->D = ctx->e_data; - E_KEY[0] = uint32_t_in (in_key); - E_KEY[1] = uint32_t_in (in_key + 4); - E_KEY[2] = uint32_t_in (in_key + 8); - E_KEY[3] = uint32_t_in (in_key + 12); + E_KEY[0] = le32_to_cpu(key[0]); + E_KEY[1] = le32_to_cpu(key[1]); + E_KEY[2] = le32_to_cpu(key[2]); + E_KEY[3] = le32_to_cpu(key[3]); /* Prepare control words. */ memset(&ctx->cword, 0, sizeof(ctx->cword)); @@ -343,17 +341,17 @@ aes_set_key(void *ctx_arg, const uint8_t *in_key, unsigned int key_len, uint32_t break; case 24: - E_KEY[4] = uint32_t_in (in_key + 16); - t = E_KEY[5] = uint32_t_in (in_key + 20); + E_KEY[4] = le32_to_cpu(key[4]); + t = E_KEY[5] = le32_to_cpu(key[5]); for (i = 0; i < 8; ++i) loop6 (i); break; case 32: - E_KEY[4] = uint32_t_in (in_key + 16); - E_KEY[5] = uint32_t_in (in_key + 20); - E_KEY[6] = uint32_t_in (in_key + 24); - t = E_KEY[7] = uint32_t_in (in_key + 28); + E_KEY[4] = le32_to_cpu(in_key[4]); + E_KEY[5] = le32_to_cpu(in_key[5]); + E_KEY[6] = le32_to_cpu(in_key[6]); + t = E_KEY[7] = le32_to_cpu(in_key[7]); for (i = 0; i < 7; ++i) loop8 (i); break; -- cgit v1.1 From 5cb1454b862ab3040b78364d58330262fea1ddba Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sat, 5 Nov 2005 16:58:14 +1100 Subject: [CRYPTO] Allow multiple implementations of the same algorithm This is the first step on the road towards asynchronous support in the Crypto API. It adds support for having multiple crypto_alg objects for the same algorithm registered in the system. For example, each device driver would register a crypto_alg object for each algorithm that it supports. While at the same time the user may load software implementations of those same algorithms. Users of the Crypto API may then select a specific implementation by name, or choose any implementation for a given algorithm with the highest priority. The priority field is a 32-bit signed integer. In future it will be possible to modify it from user-space. This also provides a solution to the problem of selecting amongst various AES implementations, that is, aes vs. aes-i586 vs. aes-padlock. Signed-off-by: Herbert Xu --- crypto/api.c | 52 ++++++++++++++++++++++++++++++++++++++++++++------ crypto/internal.h | 6 ++++++ crypto/proc.c | 6 +++--- include/linux/crypto.h | 5 +++++ 4 files changed, 60 insertions(+), 9 deletions(-) diff --git a/crypto/api.c b/crypto/api.c index 40ae42e..2715afd 100644 --- a/crypto/api.c +++ b/crypto/api.c @@ -3,6 +3,7 @@ * * Copyright (c) 2002 James Morris * Copyright (c) 2002 David S. Miller (davem@redhat.com) + * Copyright (c) 2005 Herbert Xu * * Portions derived from Cryptoapi, by Alexander Kjeldaas * and Nettle, by Niels Möller. @@ -18,9 +19,11 @@ #include #include #include +#include #include #include #include +#include #include "internal.h" LIST_HEAD(crypto_alg_list); @@ -39,6 +42,7 @@ static inline void crypto_alg_put(struct crypto_alg *alg) static struct crypto_alg *crypto_alg_lookup(const char *name) { struct crypto_alg *q, *alg = NULL; + int best = -1; if (!name) return NULL; @@ -46,11 +50,23 @@ static struct crypto_alg *crypto_alg_lookup(const char *name) down_read(&crypto_alg_sem); list_for_each_entry(q, &crypto_alg_list, cra_list) { - if (!(strcmp(q->cra_name, name))) { - if (crypto_alg_get(q)) - alg = q; + int exact, fuzzy; + + exact = !strcmp(q->cra_driver_name, name); + fuzzy = !strcmp(q->cra_name, name); + if (!exact && !(fuzzy && q->cra_priority > best)) + continue; + + if (unlikely(!crypto_alg_get(q))) + continue; + + best = q->cra_priority; + if (alg) + crypto_alg_put(alg); + alg = q; + + if (exact) break; - } } up_read(&crypto_alg_sem); @@ -207,9 +223,26 @@ void crypto_free_tfm(struct crypto_tfm *tfm) kfree(tfm); } +static inline int crypto_set_driver_name(struct crypto_alg *alg) +{ + static const char suffix[] = "-generic"; + char *driver_name = (char *)alg->cra_driver_name; + int len; + + if (*driver_name) + return 0; + + len = strlcpy(driver_name, alg->cra_name, CRYPTO_MAX_ALG_NAME); + if (len + sizeof(suffix) > CRYPTO_MAX_ALG_NAME) + return -ENAMETOOLONG; + + memcpy(driver_name + len, suffix, sizeof(suffix)); + return 0; +} + int crypto_register_alg(struct crypto_alg *alg) { - int ret = 0; + int ret; struct crypto_alg *q; if (alg->cra_alignmask & (alg->cra_alignmask + 1)) @@ -220,11 +253,18 @@ int crypto_register_alg(struct crypto_alg *alg) if (alg->cra_blocksize > PAGE_SIZE) return -EINVAL; + + if (alg->cra_priority < 0) + return -EINVAL; + ret = crypto_set_driver_name(alg); + if (unlikely(ret)) + return ret; + down_write(&crypto_alg_sem); list_for_each_entry(q, &crypto_alg_list, cra_list) { - if (!(strcmp(q->cra_name, alg->cra_name))) { + if (!strcmp(q->cra_driver_name, alg->cra_driver_name)) { ret = -EEXIST; goto out; } diff --git a/crypto/internal.h b/crypto/internal.h index 37aa652..959e602 100644 --- a/crypto/internal.h +++ b/crypto/internal.h @@ -2,6 +2,7 @@ * Cryptographic API. * * Copyright (c) 2002 James Morris + * Copyright (c) 2005 Herbert Xu * * 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 @@ -16,10 +17,15 @@ #include #include #include +#include #include +#include #include #include +extern struct list_head crypto_alg_list; +extern struct rw_semaphore crypto_alg_sem; + extern enum km_type crypto_km_types[]; static inline enum km_type crypto_kmap_type(int out) diff --git a/crypto/proc.c b/crypto/proc.c index 630ba91..c0a5dd7 100644 --- a/crypto/proc.c +++ b/crypto/proc.c @@ -4,6 +4,7 @@ * Procfs information. * * Copyright (c) 2002 James Morris + * Copyright (c) 2005 Herbert Xu * * 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 @@ -18,9 +19,6 @@ #include #include "internal.h" -extern struct list_head crypto_alg_list; -extern struct rw_semaphore crypto_alg_sem; - static void *c_start(struct seq_file *m, loff_t *pos) { struct list_head *v; @@ -53,7 +51,9 @@ static int c_show(struct seq_file *m, void *p) struct crypto_alg *alg = (struct crypto_alg *)p; seq_printf(m, "name : %s\n", alg->cra_name); + seq_printf(m, "driver : %s\n", alg->cra_driver_name); seq_printf(m, "module : %s\n", module_name(alg->cra_module)); + seq_printf(m, "priority : %d\n", alg->cra_priority); switch (alg->cra_flags & CRYPTO_ALG_TYPE_MASK) { case CRYPTO_ALG_TYPE_CIPHER: diff --git a/include/linux/crypto.h b/include/linux/crypto.h index 3c89df6..d88bf8a 100644 --- a/include/linux/crypto.h +++ b/include/linux/crypto.h @@ -3,6 +3,7 @@ * * Copyright (c) 2002 James Morris * Copyright (c) 2002 David S. Miller (davem@redhat.com) + * Copyright (c) 2005 Herbert Xu * * Portions derived from Cryptoapi, by Alexander Kjeldaas * and Nettle, by Niels Möller. @@ -126,7 +127,11 @@ struct crypto_alg { unsigned int cra_blocksize; unsigned int cra_ctxsize; unsigned int cra_alignmask; + + int cra_priority; + const char cra_name[CRYPTO_MAX_ALG_NAME]; + const char cra_driver_name[CRYPTO_MAX_ALG_NAME]; union { struct cipher_alg cipher; -- cgit v1.1 From c8a19c91b5b488fed8cce04200a84c6a35c0bf0c Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sat, 5 Nov 2005 18:06:26 +1100 Subject: [CRYPTO] Allow AES C/ASM implementations to coexist As the Crypto API now allows multiple implementations to be registered for the same algorithm, we no longer have to play tricks with Kconfig to select the right AES implementation. This patch sets the driver name and priority for all the AES implementations and removes the Kconfig conditions on the C implementation for AES. Signed-off-by: Herbert Xu --- arch/i386/crypto/aes.c | 2 ++ arch/x86_64/crypto/aes.c | 2 ++ crypto/Kconfig | 2 +- crypto/aes.c | 2 ++ drivers/crypto/padlock-aes.c | 2 ++ 5 files changed, 9 insertions(+), 1 deletion(-) diff --git a/arch/i386/crypto/aes.c b/arch/i386/crypto/aes.c index 1deb9ff..138652a 100644 --- a/arch/i386/crypto/aes.c +++ b/arch/i386/crypto/aes.c @@ -486,6 +486,8 @@ static inline void aes_decrypt(void *ctx, u8 *dst, const u8 *src) static struct crypto_alg aes_alg = { .cra_name = "aes", + .cra_driver_name = "aes-i586", + .cra_priority = 200, .cra_flags = CRYPTO_ALG_TYPE_CIPHER, .cra_blocksize = AES_BLOCK_SIZE, .cra_ctxsize = sizeof(struct aes_ctx), diff --git a/arch/x86_64/crypto/aes.c b/arch/x86_64/crypto/aes.c index 1999685..fb1b961 100644 --- a/arch/x86_64/crypto/aes.c +++ b/arch/x86_64/crypto/aes.c @@ -289,6 +289,8 @@ extern void aes_decrypt(void *ctx_arg, u8 *out, const u8 *in); static struct crypto_alg aes_alg = { .cra_name = "aes", + .cra_driver_name = "aes-x86_64", + .cra_priority = 200, .cra_flags = CRYPTO_ALG_TYPE_CIPHER, .cra_blocksize = AES_BLOCK_SIZE, .cra_ctxsize = sizeof(struct aes_ctx), diff --git a/crypto/Kconfig b/crypto/Kconfig index 52e1d41..c442f2e 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -157,7 +157,7 @@ config CRYPTO_SERPENT config CRYPTO_AES tristate "AES cipher algorithms" - depends on CRYPTO && !(X86 || UML_X86) + depends on CRYPTO help AES cipher algorithms (FIPS-197). AES uses the Rijndael algorithm. diff --git a/crypto/aes.c b/crypto/aes.c index 35a11de..b9b2afb 100644 --- a/crypto/aes.c +++ b/crypto/aes.c @@ -418,6 +418,8 @@ static void aes_decrypt(void *ctx_arg, u8 *out, const u8 *in) static struct crypto_alg aes_alg = { .cra_name = "aes", + .cra_driver_name = "aes-generic", + .cra_priority = 100, .cra_flags = CRYPTO_ALG_TYPE_CIPHER, .cra_blocksize = AES_BLOCK_SIZE, .cra_ctxsize = sizeof(struct aes_ctx), diff --git a/drivers/crypto/padlock-aes.c b/drivers/crypto/padlock-aes.c index 963e03d..64819aa 100644 --- a/drivers/crypto/padlock-aes.c +++ b/drivers/crypto/padlock-aes.c @@ -466,6 +466,8 @@ static unsigned int aes_decrypt_cbc(const struct cipher_desc *desc, u8 *out, static struct crypto_alg aes_alg = { .cra_name = "aes", + .cra_driver_name = "aes-padlock", + .cra_priority = 300, .cra_flags = CRYPTO_ALG_TYPE_CIPHER, .cra_blocksize = AES_BLOCK_SIZE, .cra_ctxsize = sizeof(struct aes_ctx), -- cgit v1.1 From cfa8d17cc836905ad174fd924701b352585d62f1 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Sun, 13 Nov 2005 10:47:20 +1100 Subject: [CRYPTO] sha1: Avoid useless memcpy() The current code unconditionally copy the first block for every call to sha1_update(). This can be avoided if there is no pending partial block. This is always the case on the first call to sha1_update() (if the length is >= 64 of course. Furthermore, temp does need to be called if sha_transform is never invoked. Also consolidate the sha_transform calls into one to reduce code size. Signed-off-by: Nicolas Pitre Signed-off-by: Herbert Xu --- crypto/sha1.c | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/crypto/sha1.c b/crypto/sha1.c index c686e78..292dcc1 100644 --- a/crypto/sha1.c +++ b/crypto/sha1.c @@ -50,22 +50,31 @@ static void sha1_update(void *ctx, const u8 *data, unsigned int len) { struct sha1_ctx *sctx = ctx; unsigned int i, j; - u32 temp[SHA_WORKSPACE_WORDS]; + const u8 *src; j = (sctx->count >> 3) & 0x3f; sctx->count += len << 3; + i = 0; + src = data; if ((j + len) > 63) { - memcpy(&sctx->buffer[j], data, (i = 64-j)); - sha_transform(sctx->state, sctx->buffer, temp); - for ( ; i + 63 < len; i += 64) { - sha_transform(sctx->state, &data[i], temp); + u32 temp[SHA_WORKSPACE_WORDS]; + + if (j) { + memcpy(&sctx->buffer[j], data, (i = 64-j)); + src = sctx->buffer; } + + do { + sha_transform(sctx->state, src, temp); + i += 64; + src = &data[i]; + } while (i + 63 < len); + + memset(temp, 0, sizeof(temp)); j = 0; } - else i = 0; - memset(temp, 0, sizeof(temp)); - memcpy(&sctx->buffer[j], &data[i], len - i); + memcpy(&sctx->buffer[j], src, len - i); } -- cgit v1.1 From 9d70a6c86cd86e111291bd0d506028ecb9649923 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Sun, 13 Nov 2005 10:59:54 +1100 Subject: [CRYPTO] sha1: Rename i/j to done/partial This patch gives more descriptive names to the variables i and j. Signed-off-by: Nicolas Pitre Signed-off-by: Herbert Xu --- crypto/sha1.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/crypto/sha1.c b/crypto/sha1.c index 292dcc1..7b1abca 100644 --- a/crypto/sha1.c +++ b/crypto/sha1.c @@ -49,32 +49,33 @@ static void sha1_init(void *ctx) static void sha1_update(void *ctx, const u8 *data, unsigned int len) { struct sha1_ctx *sctx = ctx; - unsigned int i, j; + unsigned int partial, done; const u8 *src; - j = (sctx->count >> 3) & 0x3f; + partial = (sctx->count >> 3) & 0x3f; sctx->count += len << 3; - i = 0; + done = 0; src = data; - if ((j + len) > 63) { + if ((partial + len) > 63) { u32 temp[SHA_WORKSPACE_WORDS]; - if (j) { - memcpy(&sctx->buffer[j], data, (i = 64-j)); + if (partial) { + done = 64 - partial; + memcpy(sctx->buffer + partial, data, done); src = sctx->buffer; } do { sha_transform(sctx->state, src, temp); - i += 64; - src = &data[i]; - } while (i + 63 < len); + done += 64; + src = data + done; + } while (done + 63 < len); memset(temp, 0, sizeof(temp)); - j = 0; + partial = 0; } - memcpy(&sctx->buffer[j], src, len - i); + memcpy(sctx->buffer + partial, src, len - done); } -- cgit v1.1 From fa9b98fdab5b57ecb4dd3d6c2489e262af458c44 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Sun, 13 Nov 2005 11:17:33 +1100 Subject: [CRYPTO] sha1: Avoid shifting count left and right This patch avoids shifting the count left and right needlessly for each call to sha1_update(). It instead can be done only once at the end in sha1_final(). Keeping the previous test example (sha1_update() successively called with len=64), a 1.3% performance increase can be observed on i386, or 0.2% on ARM. The generated code is also smaller on ARM. Signed-off-by: Nicolas Pitre Signed-off-by: Herbert Xu --- crypto/sha1.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crypto/sha1.c b/crypto/sha1.c index 7b1abca..8048e2d 100644 --- a/crypto/sha1.c +++ b/crypto/sha1.c @@ -52,8 +52,8 @@ static void sha1_update(void *ctx, const u8 *data, unsigned int len) unsigned int partial, done; const u8 *src; - partial = (sctx->count >> 3) & 0x3f; - sctx->count += len << 3; + partial = sctx->count & 0x3f; + sctx->count += len; done = 0; src = data; @@ -88,10 +88,10 @@ static void sha1_final(void* ctx, u8 *out) __be64 bits; static const u8 padding[64] = { 0x80, }; - bits = cpu_to_be64(sctx->count); + bits = cpu_to_be64(sctx->count << 3); /* Pad out to 56 mod 64 */ - index = (sctx->count >> 3) & 0x3f; + index = sctx->count & 0x3f; padlen = (index < 56) ? (56 - index) : ((64+56) - index); sha1_update(sctx, padding, padlen); -- cgit v1.1 From 827c3911d8551842900f44c9a139382bcae68e6e Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Tue, 29 Nov 2005 22:04:41 +1100 Subject: [CRYPTO] cipher: Align temporary buffer in cbc_process_decrypt Since the temporary buffer is used as an argument to cia_decrypt, it must be aligned by cra_alignmask. This bug was found by linux@horizon.com. Signed-off-by: Herbert Xu --- crypto/cipher.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/crypto/cipher.c b/crypto/cipher.c index dfd4bcf..65bcea0 100644 --- a/crypto/cipher.c +++ b/crypto/cipher.c @@ -212,9 +212,10 @@ static unsigned int cbc_process_decrypt(const struct cipher_desc *desc, struct crypto_tfm *tfm = desc->tfm; void (*xor)(u8 *, const u8 *) = tfm->crt_u.cipher.cit_xor_block; int bsize = crypto_tfm_alg_blocksize(tfm); + unsigned long alignmask = crypto_tfm_alg_alignmask(desc->tfm); - u8 stack[src == dst ? bsize : 0]; - u8 *buf = stack; + u8 stack[src == dst ? bsize + alignmask : 0]; + u8 *buf = (u8 *)ALIGN((unsigned long)stack, alignmask + 1); u8 **dst_p = src == dst ? &buf : &dst; void (*fn)(void *, u8 *, const u8 *) = desc->crfn; -- cgit v1.1 From e6a3a925a25ddd2ebd66dbc8d14ebdd3d57ca0c3 Mon Sep 17 00:00:00 2001 From: Denis Vlasenko Date: Tue, 29 Nov 2005 22:23:20 +1100 Subject: [CRYPTO] aes-i586: Nano-optimisation on key length check Reduce the number of comparisons by one through the use of jb/je. This patch also corrects the comments regarding the different key lengths. Signed-off-by: Herbert Xu --- arch/i386/crypto/aes-i586-asm.S | 40 +++++++++++++++++++--------------------- 1 file changed, 19 insertions(+), 21 deletions(-) diff --git a/arch/i386/crypto/aes-i586-asm.S b/arch/i386/crypto/aes-i586-asm.S index 7b73c67..911b153 100644 --- a/arch/i386/crypto/aes-i586-asm.S +++ b/arch/i386/crypto/aes-i586-asm.S @@ -255,18 +255,17 @@ aes_enc_blk: xor 8(%ebp),%r4 xor 12(%ebp),%r5 - sub $8,%esp // space for register saves on stack - add $16,%ebp // increment to next round key - sub $10,%r3 - je 4f // 10 rounds for 128-bit key - add $32,%ebp - sub $2,%r3 - je 3f // 12 rounds for 128-bit key - add $32,%ebp - -2: fwd_rnd1( -64(%ebp) ,ft_tab) // 14 rounds for 128-bit key + sub $8,%esp // space for register saves on stack + add $16,%ebp // increment to next round key + cmp $12,%r3 + jb 4f // 10 rounds for 128-bit key + lea 32(%ebp),%ebp + je 3f // 12 rounds for 192-bit key + lea 32(%ebp),%ebp + +2: fwd_rnd1( -64(%ebp) ,ft_tab) // 14 rounds for 256-bit key fwd_rnd2( -48(%ebp) ,ft_tab) -3: fwd_rnd1( -32(%ebp) ,ft_tab) // 12 rounds for 128-bit key +3: fwd_rnd1( -32(%ebp) ,ft_tab) // 12 rounds for 192-bit key fwd_rnd2( -16(%ebp) ,ft_tab) 4: fwd_rnd1( (%ebp) ,ft_tab) // 10 rounds for 128-bit key fwd_rnd2( +16(%ebp) ,ft_tab) @@ -334,18 +333,17 @@ aes_dec_blk: xor 8(%ebp),%r4 xor 12(%ebp),%r5 - sub $8,%esp // space for register saves on stack - sub $16,%ebp // increment to next round key - sub $10,%r3 - je 4f // 10 rounds for 128-bit key - sub $32,%ebp - sub $2,%r3 - je 3f // 12 rounds for 128-bit key - sub $32,%ebp + sub $8,%esp // space for register saves on stack + sub $16,%ebp // increment to next round key + cmp $12,%r3 + jb 4f // 10 rounds for 128-bit key + lea -32(%ebp),%ebp + je 3f // 12 rounds for 192-bit key + lea -32(%ebp),%ebp -2: inv_rnd1( +64(%ebp), it_tab) // 14 rounds for 128-bit key +2: inv_rnd1( +64(%ebp), it_tab) // 14 rounds for 256-bit key inv_rnd2( +48(%ebp), it_tab) -3: inv_rnd1( +32(%ebp), it_tab) // 12 rounds for 128-bit key +3: inv_rnd1( +32(%ebp), it_tab) // 12 rounds for 192-bit key inv_rnd2( +16(%ebp), it_tab) 4: inv_rnd1( (%ebp), it_tab) // 10 rounds for 128-bit key inv_rnd2( -16(%ebp), it_tab) -- cgit v1.1 From afad2608c766f53c79ec4ffccdb4bef660b90a89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=E4ki?= Date: Sat, 3 Dec 2005 17:16:42 +1100 Subject: [CRYPTO] aes-i586: Remove unused variable ls_tab MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It is assigned but never read. Signed-off-by: Daniel Marjamäki Signed-off-by: Herbert Xu --- arch/i386/crypto/aes.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/arch/i386/crypto/aes.c b/arch/i386/crypto/aes.c index 138652a..a50397b 100644 --- a/arch/i386/crypto/aes.c +++ b/arch/i386/crypto/aes.c @@ -94,7 +94,6 @@ static u32 rcon_tab[RC_LENGTH]; u32 ft_tab[4][256]; u32 fl_tab[4][256]; -static u32 ls_tab[4][256]; static u32 im_tab[4][256]; u32 il_tab[4][256]; u32 it_tab[4][256]; @@ -145,15 +144,6 @@ static void gen_tabs(void) fl_tab[2][i] = upr(w, 2); fl_tab[3][i] = upr(w, 3); - /* - * table for key schedule if fl_tab above is - * not of the required form - */ - ls_tab[0][i] = w; - ls_tab[1][i] = upr(w, 1); - ls_tab[2][i] = upr(w, 2); - ls_tab[3][i] = upr(w, 3); - b = fi(inv_affine((u8)i)); w = bytes2word(fe(b), f9(b), fd(b), fb(b)); -- cgit v1.1 From bcb0ad2b34daade529ce1f38eede0ea8b7309535 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Wed, 21 Dec 2005 19:01:58 +0800 Subject: [CRYPTO] sha1: Fixed off-by-64 bug in sha1_update After a partial update, the done pointer is off to the right by 64 bytes. Signed-off-by: Herbert Xu --- crypto/sha1.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crypto/sha1.c b/crypto/sha1.c index 8048e2d..21571ed3 100644 --- a/crypto/sha1.c +++ b/crypto/sha1.c @@ -61,8 +61,8 @@ static void sha1_update(void *ctx, const u8 *data, unsigned int len) u32 temp[SHA_WORKSPACE_WORDS]; if (partial) { - done = 64 - partial; - memcpy(sctx->buffer + partial, data, done); + done = -partial; + memcpy(sctx->buffer + partial, data, done + 64); src = sctx->buffer; } -- cgit v1.1 From 7302533aac2df321b76e8a113e5cfa529c825b09 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sat, 7 Jan 2006 16:24:15 +1100 Subject: [CRYPTO] api: Require block size to be less than PAGE_SIZE/8 The cipher code path may allocate up to two blocks of data on the stack. Therefore we need to place limits on the maximum block size. Signed-off-by: Herbert Xu --- crypto/api.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crypto/api.c b/crypto/api.c index 2715afd..e26156f 100644 --- a/crypto/api.c +++ b/crypto/api.c @@ -251,7 +251,7 @@ int crypto_register_alg(struct crypto_alg *alg) if (alg->cra_alignmask & alg->cra_blocksize) return -EINVAL; - if (alg->cra_blocksize > PAGE_SIZE) + if (alg->cra_blocksize > PAGE_SIZE / 8) return -EINVAL; if (alg->cra_priority < 0) -- cgit v1.1 From a429d2609c153882c421b067ad5ae5a38851459e Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sat, 7 Jan 2006 16:38:15 +1100 Subject: [CRYPTO] cipher: Set alignmask for multi-byte loads Many cipher implementations use 4-byte/8-byte loads/stores which require alignment on some architectures. This patch explicitly sets the alignment requirements for them. Signed-off-by: Herbert Xu --- crypto/aes.c | 1 + crypto/anubis.c | 1 + crypto/blowfish.c | 1 + crypto/cast5.c | 1 + crypto/cast6.c | 1 + crypto/des.c | 1 + crypto/khazad.c | 1 + crypto/serpent.c | 1 + crypto/tea.c | 3 +++ crypto/twofish.c | 1 + 10 files changed, 12 insertions(+) diff --git a/crypto/aes.c b/crypto/aes.c index b9b2afb..0a6a5c1 100644 --- a/crypto/aes.c +++ b/crypto/aes.c @@ -423,6 +423,7 @@ static struct crypto_alg aes_alg = { .cra_flags = CRYPTO_ALG_TYPE_CIPHER, .cra_blocksize = AES_BLOCK_SIZE, .cra_ctxsize = sizeof(struct aes_ctx), + .cra_alignmask = 3, .cra_module = THIS_MODULE, .cra_list = LIST_HEAD_INIT(aes_alg.cra_list), .cra_u = { diff --git a/crypto/anubis.c b/crypto/anubis.c index 94c4b1f..2c796bd 100644 --- a/crypto/anubis.c +++ b/crypto/anubis.c @@ -677,6 +677,7 @@ static struct crypto_alg anubis_alg = { .cra_flags = CRYPTO_ALG_TYPE_CIPHER, .cra_blocksize = ANUBIS_BLOCK_SIZE, .cra_ctxsize = sizeof (struct anubis_ctx), + .cra_alignmask = 3, .cra_module = THIS_MODULE, .cra_list = LIST_HEAD_INIT(anubis_alg.cra_list), .cra_u = { .cipher = { diff --git a/crypto/blowfish.c b/crypto/blowfish.c index 99fc459..7f710b2 100644 --- a/crypto/blowfish.c +++ b/crypto/blowfish.c @@ -453,6 +453,7 @@ static struct crypto_alg alg = { .cra_flags = CRYPTO_ALG_TYPE_CIPHER, .cra_blocksize = BF_BLOCK_SIZE, .cra_ctxsize = sizeof(struct bf_ctx), + .cra_alignmask = 3, .cra_module = THIS_MODULE, .cra_list = LIST_HEAD_INIT(alg.cra_list), .cra_u = { .cipher = { diff --git a/crypto/cast5.c b/crypto/cast5.c index 282641c..8834c85 100644 --- a/crypto/cast5.c +++ b/crypto/cast5.c @@ -809,6 +809,7 @@ static struct crypto_alg alg = { .cra_flags = CRYPTO_ALG_TYPE_CIPHER, .cra_blocksize = CAST5_BLOCK_SIZE, .cra_ctxsize = sizeof(struct cast5_ctx), + .cra_alignmask = 3, .cra_module = THIS_MODULE, .cra_list = LIST_HEAD_INIT(alg.cra_list), .cra_u = { diff --git a/crypto/cast6.c b/crypto/cast6.c index d317fff..9e28740 100644 --- a/crypto/cast6.c +++ b/crypto/cast6.c @@ -513,6 +513,7 @@ static struct crypto_alg alg = { .cra_flags = CRYPTO_ALG_TYPE_CIPHER, .cra_blocksize = CAST6_BLOCK_SIZE, .cra_ctxsize = sizeof(struct cast6_ctx), + .cra_alignmask = 3, .cra_module = THIS_MODULE, .cra_list = LIST_HEAD_INIT(alg.cra_list), .cra_u = { diff --git a/crypto/des.c b/crypto/des.c index dae4298..7bb5486 100644 --- a/crypto/des.c +++ b/crypto/des.c @@ -949,6 +949,7 @@ static struct crypto_alg des_alg = { .cra_blocksize = DES_BLOCK_SIZE, .cra_ctxsize = sizeof(struct des_ctx), .cra_module = THIS_MODULE, + .cra_alignmask = 3, .cra_list = LIST_HEAD_INIT(des_alg.cra_list), .cra_u = { .cipher = { .cia_min_keysize = DES_KEY_SIZE, diff --git a/crypto/khazad.c b/crypto/khazad.c index 6809210..807f2bf 100644 --- a/crypto/khazad.c +++ b/crypto/khazad.c @@ -857,6 +857,7 @@ static struct crypto_alg khazad_alg = { .cra_flags = CRYPTO_ALG_TYPE_CIPHER, .cra_blocksize = KHAZAD_BLOCK_SIZE, .cra_ctxsize = sizeof (struct khazad_ctx), + .cra_alignmask = 7, .cra_module = THIS_MODULE, .cra_list = LIST_HEAD_INIT(khazad_alg.cra_list), .cra_u = { .cipher = { diff --git a/crypto/serpent.c b/crypto/serpent.c index a950ff8..52ad1a4 100644 --- a/crypto/serpent.c +++ b/crypto/serpent.c @@ -553,6 +553,7 @@ static struct crypto_alg tnepres_alg = { .cra_flags = CRYPTO_ALG_TYPE_CIPHER, .cra_blocksize = SERPENT_BLOCK_SIZE, .cra_ctxsize = sizeof(struct serpent_ctx), + .cra_alignmask = 3, .cra_module = THIS_MODULE, .cra_list = LIST_HEAD_INIT(serpent_alg.cra_list), .cra_u = { .cipher = { diff --git a/crypto/tea.c b/crypto/tea.c index e0077c7..a6a02b3 100644 --- a/crypto/tea.c +++ b/crypto/tea.c @@ -240,6 +240,7 @@ static struct crypto_alg tea_alg = { .cra_flags = CRYPTO_ALG_TYPE_CIPHER, .cra_blocksize = TEA_BLOCK_SIZE, .cra_ctxsize = sizeof (struct tea_ctx), + .cra_alignmask = 3, .cra_module = THIS_MODULE, .cra_list = LIST_HEAD_INIT(tea_alg.cra_list), .cra_u = { .cipher = { @@ -255,6 +256,7 @@ static struct crypto_alg xtea_alg = { .cra_flags = CRYPTO_ALG_TYPE_CIPHER, .cra_blocksize = XTEA_BLOCK_SIZE, .cra_ctxsize = sizeof (struct xtea_ctx), + .cra_alignmask = 3, .cra_module = THIS_MODULE, .cra_list = LIST_HEAD_INIT(xtea_alg.cra_list), .cra_u = { .cipher = { @@ -270,6 +272,7 @@ static struct crypto_alg xeta_alg = { .cra_flags = CRYPTO_ALG_TYPE_CIPHER, .cra_blocksize = XTEA_BLOCK_SIZE, .cra_ctxsize = sizeof (struct xtea_ctx), + .cra_alignmask = 3, .cra_module = THIS_MODULE, .cra_list = LIST_HEAD_INIT(xtea_alg.cra_list), .cra_u = { .cipher = { diff --git a/crypto/twofish.c b/crypto/twofish.c index b501d5a..a26d885 100644 --- a/crypto/twofish.c +++ b/crypto/twofish.c @@ -879,6 +879,7 @@ static struct crypto_alg alg = { .cra_flags = CRYPTO_ALG_TYPE_CIPHER, .cra_blocksize = TF_BLOCK_SIZE, .cra_ctxsize = sizeof(struct twofish_ctx), + .cra_alignmask = 3, .cra_module = THIS_MODULE, .cra_list = LIST_HEAD_INIT(alg.cra_list), .cra_u = { .cipher = { -- cgit v1.1 From 2941a4863154982918d39a639632c76eeacfa884 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Sun, 8 Jan 2006 22:05:26 -0800 Subject: [NET]: Convert net/{ipv4,ipv6,sched} to netdev_priv Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/ipv4/ip_gre.c | 33 +++++++++++++++------------------ net/ipv4/ipip.c | 18 +++++++++--------- net/ipv4/ipmr.c | 22 +++++++++++----------- net/ipv6/ip6_tunnel.c | 24 ++++++++++++------------ net/ipv6/sit.c | 20 ++++++++++---------- net/sched/sch_teql.c | 12 ++++++------ 6 files changed, 63 insertions(+), 66 deletions(-) diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index de16e94..1e93eaf 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c @@ -188,7 +188,7 @@ static struct ip_tunnel * ipgre_tunnel_lookup(u32 remote, u32 local, u32 key) } if (ipgre_fb_tunnel_dev->flags&IFF_UP) - return ipgre_fb_tunnel_dev->priv; + return netdev_priv(ipgre_fb_tunnel_dev); return NULL; } @@ -278,7 +278,7 @@ static struct ip_tunnel * ipgre_tunnel_locate(struct ip_tunnel_parm *parms, int return NULL; dev->init = ipgre_tunnel_init; - nt = dev->priv; + nt = netdev_priv(dev); nt->parms = *parms; if (register_netdevice(dev) < 0) { @@ -286,9 +286,6 @@ static struct ip_tunnel * ipgre_tunnel_locate(struct ip_tunnel_parm *parms, int goto failed; } - nt = dev->priv; - nt->parms = *parms; - dev_hold(dev); ipgre_tunnel_link(nt); return nt; @@ -299,7 +296,7 @@ failed: static void ipgre_tunnel_uninit(struct net_device *dev) { - ipgre_tunnel_unlink((struct ip_tunnel*)dev->priv); + ipgre_tunnel_unlink(netdev_priv(dev)); dev_put(dev); } @@ -518,7 +515,7 @@ out: skb2->dst->ops->update_pmtu(skb2->dst, rel_info); rel_info = htonl(rel_info); } else if (type == ICMP_TIME_EXCEEDED) { - struct ip_tunnel *t = (struct ip_tunnel*)skb2->dev->priv; + struct ip_tunnel *t = netdev_priv(skb2->dev); if (t->parms.iph.ttl) { rel_type = ICMP_DEST_UNREACH; rel_code = ICMP_HOST_UNREACH; @@ -669,7 +666,7 @@ drop_nolock: static int ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) { - struct ip_tunnel *tunnel = (struct ip_tunnel*)dev->priv; + struct ip_tunnel *tunnel = netdev_priv(dev); struct net_device_stats *stats = &tunnel->stat; struct iphdr *old_iph = skb->nh.iph; struct iphdr *tiph; @@ -915,7 +912,7 @@ ipgre_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) t = ipgre_tunnel_locate(&p, 0); } if (t == NULL) - t = (struct ip_tunnel*)dev->priv; + t = netdev_priv(dev); memcpy(&p, &t->parms, sizeof(p)); if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof(p))) err = -EFAULT; @@ -955,7 +952,7 @@ ipgre_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) } else { unsigned nflags=0; - t = (struct ip_tunnel*)dev->priv; + t = netdev_priv(dev); if (MULTICAST(p.iph.daddr)) nflags = IFF_BROADCAST; @@ -1004,7 +1001,7 @@ ipgre_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) if ((t = ipgre_tunnel_locate(&p, 0)) == NULL) goto done; err = -EPERM; - if (t == ipgre_fb_tunnel_dev->priv) + if (t == netdev_priv(ipgre_fb_tunnel_dev)) goto done; dev = t->dev; } @@ -1021,12 +1018,12 @@ done: static struct net_device_stats *ipgre_tunnel_get_stats(struct net_device *dev) { - return &(((struct ip_tunnel*)dev->priv)->stat); + return &(((struct ip_tunnel*)netdev_priv(dev))->stat); } static int ipgre_tunnel_change_mtu(struct net_device *dev, int new_mtu) { - struct ip_tunnel *tunnel = (struct ip_tunnel*)dev->priv; + struct ip_tunnel *tunnel = netdev_priv(dev); if (new_mtu < 68 || new_mtu > 0xFFF8 - tunnel->hlen) return -EINVAL; dev->mtu = new_mtu; @@ -1066,7 +1063,7 @@ static int ipgre_tunnel_change_mtu(struct net_device *dev, int new_mtu) static int ipgre_header(struct sk_buff *skb, struct net_device *dev, unsigned short type, void *daddr, void *saddr, unsigned len) { - struct ip_tunnel *t = (struct ip_tunnel*)dev->priv; + struct ip_tunnel *t = netdev_priv(dev); struct iphdr *iph = (struct iphdr *)skb_push(skb, t->hlen); u16 *p = (u16*)(iph+1); @@ -1093,7 +1090,7 @@ static int ipgre_header(struct sk_buff *skb, struct net_device *dev, unsigned sh static int ipgre_open(struct net_device *dev) { - struct ip_tunnel *t = (struct ip_tunnel*)dev->priv; + struct ip_tunnel *t = netdev_priv(dev); if (MULTICAST(t->parms.iph.daddr)) { struct flowi fl = { .oif = t->parms.link, @@ -1117,7 +1114,7 @@ static int ipgre_open(struct net_device *dev) static int ipgre_close(struct net_device *dev) { - struct ip_tunnel *t = (struct ip_tunnel*)dev->priv; + struct ip_tunnel *t = netdev_priv(dev); if (MULTICAST(t->parms.iph.daddr) && t->mlink) { struct in_device *in_dev = inetdev_by_index(t->mlink); if (in_dev) { @@ -1157,7 +1154,7 @@ static int ipgre_tunnel_init(struct net_device *dev) int mtu = ETH_DATA_LEN; int addend = sizeof(struct iphdr) + 4; - tunnel = (struct ip_tunnel*)dev->priv; + tunnel = netdev_priv(dev); iph = &tunnel->parms.iph; tunnel->dev = dev; @@ -1221,7 +1218,7 @@ static int ipgre_tunnel_init(struct net_device *dev) static int __init ipgre_fb_tunnel_init(struct net_device *dev) { - struct ip_tunnel *tunnel = (struct ip_tunnel*)dev->priv; + struct ip_tunnel *tunnel = netdev_priv(dev); struct iphdr *iph = &tunnel->parms.iph; tunnel->dev = dev; diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c index bbd85f5..bc5ca23 100644 --- a/net/ipv4/ipip.c +++ b/net/ipv4/ipip.c @@ -244,7 +244,7 @@ static struct ip_tunnel * ipip_tunnel_locate(struct ip_tunnel_parm *parms, int c if (dev == NULL) return NULL; - nt = dev->priv; + nt = netdev_priv(dev); SET_MODULE_OWNER(dev); dev->init = ipip_tunnel_init; nt->parms = *parms; @@ -269,7 +269,7 @@ static void ipip_tunnel_uninit(struct net_device *dev) tunnels_wc[0] = NULL; write_unlock_bh(&ipip_lock); } else - ipip_tunnel_unlink((struct ip_tunnel*)dev->priv); + ipip_tunnel_unlink(netdev_priv(dev)); dev_put(dev); } @@ -443,7 +443,7 @@ out: skb2->dst->ops->update_pmtu(skb2->dst, rel_info); rel_info = htonl(rel_info); } else if (type == ICMP_TIME_EXCEEDED) { - struct ip_tunnel *t = (struct ip_tunnel*)skb2->dev->priv; + struct ip_tunnel *t = netdev_priv(skb2->dev); if (t->parms.iph.ttl) { rel_type = ICMP_DEST_UNREACH; rel_code = ICMP_HOST_UNREACH; @@ -514,7 +514,7 @@ out: static int ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) { - struct ip_tunnel *tunnel = (struct ip_tunnel*)dev->priv; + struct ip_tunnel *tunnel = netdev_priv(dev); struct net_device_stats *stats = &tunnel->stat; struct iphdr *tiph = &tunnel->parms.iph; u8 tos = tunnel->parms.iph.tos; @@ -674,7 +674,7 @@ ipip_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) t = ipip_tunnel_locate(&p, 0); } if (t == NULL) - t = (struct ip_tunnel*)dev->priv; + t = netdev_priv(dev); memcpy(&p, &t->parms, sizeof(p)); if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof(p))) err = -EFAULT; @@ -711,7 +711,7 @@ ipip_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) err = -EINVAL; break; } - t = (struct ip_tunnel*)dev->priv; + t = netdev_priv(dev); ipip_tunnel_unlink(t); t->parms.iph.saddr = p.iph.saddr; t->parms.iph.daddr = p.iph.daddr; @@ -765,7 +765,7 @@ done: static struct net_device_stats *ipip_tunnel_get_stats(struct net_device *dev) { - return &(((struct ip_tunnel*)dev->priv)->stat); + return &(((struct ip_tunnel*)netdev_priv(dev))->stat); } static int ipip_tunnel_change_mtu(struct net_device *dev, int new_mtu) @@ -800,7 +800,7 @@ static int ipip_tunnel_init(struct net_device *dev) struct ip_tunnel *tunnel; struct iphdr *iph; - tunnel = (struct ip_tunnel*)dev->priv; + tunnel = netdev_priv(dev); iph = &tunnel->parms.iph; tunnel->dev = dev; @@ -838,7 +838,7 @@ static int ipip_tunnel_init(struct net_device *dev) static int __init ipip_fb_tunnel_init(struct net_device *dev) { - struct ip_tunnel *tunnel = dev->priv; + struct ip_tunnel *tunnel = netdev_priv(dev); struct iphdr *iph = &tunnel->parms.iph; tunnel->dev = dev; diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index 9a5c0ce..f58ac98 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c @@ -178,8 +178,8 @@ static int reg_vif_num = -1; static int reg_vif_xmit(struct sk_buff *skb, struct net_device *dev) { read_lock(&mrt_lock); - ((struct net_device_stats*)dev->priv)->tx_bytes += skb->len; - ((struct net_device_stats*)dev->priv)->tx_packets++; + ((struct net_device_stats*)netdev_priv(dev))->tx_bytes += skb->len; + ((struct net_device_stats*)netdev_priv(dev))->tx_packets++; ipmr_cache_report(skb, reg_vif_num, IGMPMSG_WHOLEPKT); read_unlock(&mrt_lock); kfree_skb(skb); @@ -188,7 +188,7 @@ static int reg_vif_xmit(struct sk_buff *skb, struct net_device *dev) static struct net_device_stats *reg_vif_get_stats(struct net_device *dev) { - return (struct net_device_stats*)dev->priv; + return (struct net_device_stats*)netdev_priv(dev); } static void reg_vif_setup(struct net_device *dev) @@ -1149,8 +1149,8 @@ static void ipmr_queue_xmit(struct sk_buff *skb, struct mfc_cache *c, int vifi) if (vif->flags & VIFF_REGISTER) { vif->pkt_out++; vif->bytes_out+=skb->len; - ((struct net_device_stats*)vif->dev->priv)->tx_bytes += skb->len; - ((struct net_device_stats*)vif->dev->priv)->tx_packets++; + ((struct net_device_stats*)netdev_priv(vif->dev))->tx_bytes += skb->len; + ((struct net_device_stats*)netdev_priv(vif->dev))->tx_packets++; ipmr_cache_report(skb, vifi, IGMPMSG_WHOLEPKT); kfree_skb(skb); return; @@ -1210,8 +1210,8 @@ static void ipmr_queue_xmit(struct sk_buff *skb, struct mfc_cache *c, int vifi) if (vif->flags & VIFF_TUNNEL) { ip_encap(skb, vif->local, vif->remote); /* FIXME: extra output firewall step used to be here. --RR */ - ((struct ip_tunnel *)vif->dev->priv)->stat.tx_packets++; - ((struct ip_tunnel *)vif->dev->priv)->stat.tx_bytes+=skb->len; + ((struct ip_tunnel *)netdev_priv(vif->dev))->stat.tx_packets++; + ((struct ip_tunnel *)netdev_priv(vif->dev))->stat.tx_bytes+=skb->len; } IPCB(skb)->flags |= IPSKB_FORWARDED; @@ -1467,8 +1467,8 @@ int pim_rcv_v1(struct sk_buff * skb) skb->pkt_type = PACKET_HOST; dst_release(skb->dst); skb->dst = NULL; - ((struct net_device_stats*)reg_dev->priv)->rx_bytes += skb->len; - ((struct net_device_stats*)reg_dev->priv)->rx_packets++; + ((struct net_device_stats*)netdev_priv(reg_dev))->rx_bytes += skb->len; + ((struct net_device_stats*)netdev_priv(reg_dev))->rx_packets++; nf_reset(skb); netif_rx(skb); dev_put(reg_dev); @@ -1522,8 +1522,8 @@ static int pim_rcv(struct sk_buff * skb) skb->ip_summed = 0; skb->pkt_type = PACKET_HOST; dst_release(skb->dst); - ((struct net_device_stats*)reg_dev->priv)->rx_bytes += skb->len; - ((struct net_device_stats*)reg_dev->priv)->rx_packets++; + ((struct net_device_stats*)netdev_priv(reg_dev))->rx_bytes += skb->len; + ((struct net_device_stats*)netdev_priv(reg_dev))->rx_packets++; skb->dst = NULL; nf_reset(skb); netif_rx(skb); diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index f079621..c3c2bf6 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c @@ -243,7 +243,7 @@ ip6_tnl_create(struct ip6_tnl_parm *p, struct ip6_tnl **pt) if (dev == NULL) return -ENOMEM; - t = dev->priv; + t = netdev_priv(dev); dev->init = ip6ip6_tnl_dev_init; t->parms = *p; @@ -308,7 +308,7 @@ ip6ip6_tnl_locate(struct ip6_tnl_parm *p, struct ip6_tnl **pt, int create) static void ip6ip6_tnl_dev_uninit(struct net_device *dev) { - struct ip6_tnl *t = dev->priv; + struct ip6_tnl *t = netdev_priv(dev); if (dev == ip6ip6_fb_tnl_dev) { write_lock_bh(&ip6ip6_lock); @@ -623,7 +623,7 @@ ip6ip6_tnl_addr_conflict(struct ip6_tnl *t, struct ipv6hdr *hdr) static int ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev) { - struct ip6_tnl *t = (struct ip6_tnl *) dev->priv; + struct ip6_tnl *t = netdev_priv(dev); struct net_device_stats *stats = &t->stat; struct ipv6hdr *ipv6h = skb->nh.ipv6h; struct ipv6_txoptions *opt = NULL; @@ -933,11 +933,11 @@ ip6ip6_tnl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) break; } if ((err = ip6ip6_tnl_locate(&p, &t, 0)) == -ENODEV) - t = (struct ip6_tnl *) dev->priv; + t = netdev_priv(dev); else if (err) break; } else - t = (struct ip6_tnl *) dev->priv; + t = netdev_priv(dev); memcpy(&p, &t->parms, sizeof (p)); if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof (p))) { @@ -955,7 +955,7 @@ ip6ip6_tnl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) break; } if (!create && dev != ip6ip6_fb_tnl_dev) { - t = (struct ip6_tnl *) dev->priv; + t = netdev_priv(dev); } if (!t && (err = ip6ip6_tnl_locate(&p, &t, create))) { break; @@ -991,12 +991,12 @@ ip6ip6_tnl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) err = ip6ip6_tnl_locate(&p, &t, 0); if (err) break; - if (t == ip6ip6_fb_tnl_dev->priv) { + if (t == netdev_priv(ip6ip6_fb_tnl_dev)) { err = -EPERM; break; } } else { - t = (struct ip6_tnl *) dev->priv; + t = netdev_priv(dev); } err = unregister_netdevice(t->dev); break; @@ -1016,7 +1016,7 @@ ip6ip6_tnl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) static struct net_device_stats * ip6ip6_tnl_get_stats(struct net_device *dev) { - return &(((struct ip6_tnl *) dev->priv)->stat); + return &(((struct ip6_tnl *)netdev_priv(dev))->stat); } /** @@ -1073,7 +1073,7 @@ static void ip6ip6_tnl_dev_setup(struct net_device *dev) static inline void ip6ip6_tnl_dev_init_gen(struct net_device *dev) { - struct ip6_tnl *t = (struct ip6_tnl *) dev->priv; + struct ip6_tnl *t = netdev_priv(dev); t->fl.proto = IPPROTO_IPV6; t->dev = dev; strcpy(t->parms.name, dev->name); @@ -1087,7 +1087,7 @@ ip6ip6_tnl_dev_init_gen(struct net_device *dev) static int ip6ip6_tnl_dev_init(struct net_device *dev) { - struct ip6_tnl *t = (struct ip6_tnl *) dev->priv; + struct ip6_tnl *t = netdev_priv(dev); ip6ip6_tnl_dev_init_gen(dev); ip6ip6_tnl_link_config(t); return 0; @@ -1103,7 +1103,7 @@ ip6ip6_tnl_dev_init(struct net_device *dev) static int ip6ip6_fb_tnl_dev_init(struct net_device *dev) { - struct ip6_tnl *t = dev->priv; + struct ip6_tnl *t = netdev_priv(dev); ip6ip6_tnl_dev_init_gen(dev); dev_hold(dev); tnls_wc[0] = t; diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 02872ae..0dae48a 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c @@ -184,7 +184,7 @@ static struct ip_tunnel * ipip6_tunnel_locate(struct ip_tunnel_parm *parms, int if (dev == NULL) return NULL; - nt = dev->priv; + nt = netdev_priv(dev); dev->init = ipip6_tunnel_init; nt->parms = *parms; @@ -210,7 +210,7 @@ static void ipip6_tunnel_uninit(struct net_device *dev) write_unlock_bh(&ipip6_lock); dev_put(dev); } else { - ipip6_tunnel_unlink((struct ip_tunnel*)dev->priv); + ipip6_tunnel_unlink(netdev_priv(dev)); dev_put(dev); } } @@ -346,7 +346,7 @@ out: rt6i = rt6_lookup(&iph6->daddr, &iph6->saddr, NULL, 0); if (rt6i && rt6i->rt6i_dev && rt6i->rt6i_dev->type == ARPHRD_SIT) { - struct ip_tunnel * t = (struct ip_tunnel*)rt6i->rt6i_dev->priv; + struct ip_tunnel *t = netdev_priv(rt6i->rt6i_dev); if (rel_type == ICMPV6_TIME_EXCEED && t->parms.iph.ttl) { rel_type = ICMPV6_DEST_UNREACH; rel_code = ICMPV6_ADDR_UNREACH; @@ -424,7 +424,7 @@ static inline u32 try_6to4(struct in6_addr *v6dst) static int ipip6_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) { - struct ip_tunnel *tunnel = (struct ip_tunnel*)dev->priv; + struct ip_tunnel *tunnel = netdev_priv(dev); struct net_device_stats *stats = &tunnel->stat; struct iphdr *tiph = &tunnel->parms.iph; struct ipv6hdr *iph6 = skb->nh.ipv6h; @@ -610,7 +610,7 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) t = ipip6_tunnel_locate(&p, 0); } if (t == NULL) - t = (struct ip_tunnel*)dev->priv; + t = netdev_priv(dev); memcpy(&p, &t->parms, sizeof(p)); if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof(p))) err = -EFAULT; @@ -647,7 +647,7 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) err = -EINVAL; break; } - t = (struct ip_tunnel*)dev->priv; + t = netdev_priv(dev); ipip6_tunnel_unlink(t); t->parms.iph.saddr = p.iph.saddr; t->parms.iph.daddr = p.iph.daddr; @@ -683,7 +683,7 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) if ((t = ipip6_tunnel_locate(&p, 0)) == NULL) goto done; err = -EPERM; - if (t == ipip6_fb_tunnel_dev->priv) + if (t == netdev_priv(ipip6_fb_tunnel_dev)) goto done; dev = t->dev; } @@ -700,7 +700,7 @@ done: static struct net_device_stats *ipip6_tunnel_get_stats(struct net_device *dev) { - return &(((struct ip_tunnel*)dev->priv)->stat); + return &(((struct ip_tunnel*)netdev_priv(dev))->stat); } static int ipip6_tunnel_change_mtu(struct net_device *dev, int new_mtu) @@ -735,7 +735,7 @@ static int ipip6_tunnel_init(struct net_device *dev) struct ip_tunnel *tunnel; struct iphdr *iph; - tunnel = (struct ip_tunnel*)dev->priv; + tunnel = netdev_priv(dev); iph = &tunnel->parms.iph; tunnel->dev = dev; @@ -775,7 +775,7 @@ static int ipip6_tunnel_init(struct net_device *dev) static int __init ipip6_fb_tunnel_init(struct net_device *dev) { - struct ip_tunnel *tunnel = dev->priv; + struct ip_tunnel *tunnel = netdev_priv(dev); struct iphdr *iph = &tunnel->parms.iph; tunnel->dev = dev; diff --git a/net/sched/sch_teql.c b/net/sched/sch_teql.c index c4a2a8c..79b8ef3 100644 --- a/net/sched/sch_teql.c +++ b/net/sched/sch_teql.c @@ -274,7 +274,7 @@ teql_resolve(struct sk_buff *skb, struct sk_buff *skb_res, struct net_device *de static int teql_master_xmit(struct sk_buff *skb, struct net_device *dev) { - struct teql_master *master = (void*)dev->priv; + struct teql_master *master = netdev_priv(dev); struct Qdisc *start, *q; int busy; int nores; @@ -350,7 +350,7 @@ drop: static int teql_master_open(struct net_device *dev) { struct Qdisc * q; - struct teql_master *m = (void*)dev->priv; + struct teql_master *m = netdev_priv(dev); int mtu = 0xFFFE; unsigned flags = IFF_NOARP|IFF_MULTICAST; @@ -397,13 +397,13 @@ static int teql_master_close(struct net_device *dev) static struct net_device_stats *teql_master_stats(struct net_device *dev) { - struct teql_master *m = (void*)dev->priv; + struct teql_master *m = netdev_priv(dev); return &m->stats; } static int teql_master_mtu(struct net_device *dev, int new_mtu) { - struct teql_master *m = (void*)dev->priv; + struct teql_master *m = netdev_priv(dev); struct Qdisc *q; if (new_mtu < 68) @@ -423,7 +423,7 @@ static int teql_master_mtu(struct net_device *dev, int new_mtu) static __init void teql_master_setup(struct net_device *dev) { - struct teql_master *master = dev->priv; + struct teql_master *master = netdev_priv(dev); struct Qdisc_ops *ops = &master->qops; master->dev = dev; @@ -476,7 +476,7 @@ static int __init teql_init(void) break; } - master = dev->priv; + master = netdev_priv(dev); strlcpy(master->qops.id, dev->name, IFNAMSIZ); err = register_qdisc(&master->qops); -- cgit v1.1 From 538e43a4bd36ae49873ef7097a16a207f5d9912b Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Sun, 8 Jan 2006 22:12:03 -0800 Subject: [PKT_SCHED]: Use USEC_PER_SEC Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- include/net/pkt_sched.h | 23 ++++++++++++----------- net/sched/sch_hfsc.c | 8 ++++---- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/include/net/pkt_sched.h b/include/net/pkt_sched.h index 6492e73..b94d1ad 100644 --- a/include/net/pkt_sched.h +++ b/include/net/pkt_sched.h @@ -1,6 +1,7 @@ #ifndef __NET_PKT_SCHED_H #define __NET_PKT_SCHED_H +#include #include struct qdisc_walker @@ -59,8 +60,8 @@ typedef struct timeval psched_time_t; typedef long psched_tdiff_t; #define PSCHED_GET_TIME(stamp) do_gettimeofday(&(stamp)) -#define PSCHED_US2JIFFIE(usecs) (((usecs)+(1000000/HZ-1))/(1000000/HZ)) -#define PSCHED_JIFFIE2US(delay) ((delay)*(1000000/HZ)) +#define PSCHED_US2JIFFIE(usecs) usecs_to_jiffies(usecs) +#define PSCHED_JIFFIE2US(delay) jiffies_to_usecs(delay) #else /* !CONFIG_NET_SCH_CLK_GETTIMEOFDAY */ @@ -123,9 +124,9 @@ do { \ default: \ __delta = 0; \ case 2: \ - __delta += 1000000; \ + __delta += USEC_PER_SEC; \ case 1: \ - __delta += 1000000; \ + __delta += USEC_PER_SEC; \ } \ } \ __delta; \ @@ -136,9 +137,9 @@ psched_tod_diff(int delta_sec, int bound) { int delta; - if (bound <= 1000000 || delta_sec > (0x7FFFFFFF/1000000)-1) + if (bound <= USEC_PER_SEC || delta_sec > (0x7FFFFFFF/USEC_PER_SEC)-1) return bound; - delta = delta_sec * 1000000; + delta = delta_sec * USEC_PER_SEC; if (delta > bound || delta < 0) delta = bound; return delta; @@ -152,9 +153,9 @@ psched_tod_diff(int delta_sec, int bound) default: \ __delta = psched_tod_diff(__delta_sec, bound); break; \ case 2: \ - __delta += 1000000; \ + __delta += USEC_PER_SEC; \ case 1: \ - __delta += 1000000; \ + __delta += USEC_PER_SEC; \ case 0: \ if (__delta > bound || __delta < 0) \ __delta = bound; \ @@ -170,15 +171,15 @@ psched_tod_diff(int delta_sec, int bound) ({ \ int __delta = (tv).tv_usec + (delta); \ (tv_res).tv_sec = (tv).tv_sec; \ - if (__delta > 1000000) { (tv_res).tv_sec++; __delta -= 1000000; } \ + if (__delta > USEC_PER_SEC) { (tv_res).tv_sec++; __delta -= USEC_PER_SEC; } \ (tv_res).tv_usec = __delta; \ }) #define PSCHED_TADD(tv, delta) \ ({ \ (tv).tv_usec += (delta); \ - if ((tv).tv_usec > 1000000) { (tv).tv_sec++; \ - (tv).tv_usec -= 1000000; } \ + if ((tv).tv_usec > USEC_PER_SEC) { (tv).tv_sec++; \ + (tv).tv_usec -= USEC_PER_SEC; } \ }) /* Set/check that time is in the "past perfect"; diff --git a/net/sched/sch_hfsc.c b/net/sched/sch_hfsc.c index c26764b..cad1758 100644 --- a/net/sched/sch_hfsc.c +++ b/net/sched/sch_hfsc.c @@ -208,7 +208,7 @@ struct hfsc_sched do { \ struct timeval tv; \ do_gettimeofday(&tv); \ - (stamp) = 1000000ULL * tv.tv_sec + tv.tv_usec; \ + (stamp) = 1ULL * USEC_PER_SEC * tv.tv_sec + tv.tv_usec; \ } while (0) #endif @@ -502,8 +502,8 @@ d2dx(u32 d) u64 dx; dx = ((u64)d * PSCHED_JIFFIE2US(HZ)); - dx += 1000000 - 1; - do_div(dx, 1000000); + dx += USEC_PER_SEC - 1; + do_div(dx, USEC_PER_SEC); return dx; } @@ -523,7 +523,7 @@ dx2d(u64 dx) { u64 d; - d = dx * 1000000; + d = dx * USEC_PER_SEC; do_div(d, PSCHED_JIFFIE2US(HZ)); return (u32)d; } -- cgit v1.1 From f43c5a0df38e12f53a3023175a12da9b7ef0df63 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Sun, 8 Jan 2006 22:15:34 -0800 Subject: [PKT_SCHED]: Convert tc action functions to single skb pointers tcf_action_exec only gets a single skb pointer and doesn't own the skb, but passes double skb pointers (to a local variable) to the action functions. Change to use single skb pointers everywhere. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- include/net/act_api.h | 2 +- net/sched/act_api.c | 2 +- net/sched/gact.c | 3 +-- net/sched/ipt.c | 6 ++++-- net/sched/mirred.c | 3 +-- net/sched/pedit.c | 3 +-- net/sched/police.c | 3 +-- net/sched/simple.c | 3 +-- 8 files changed, 11 insertions(+), 14 deletions(-) diff --git a/include/net/act_api.h b/include/net/act_api.h index b55eb7c..11e9eaf 100644 --- a/include/net/act_api.h +++ b/include/net/act_api.h @@ -63,7 +63,7 @@ struct tc_action_ops __u32 type; /* TBD to match kind */ __u32 capab; /* capabilities includes 4 bit version */ struct module *owner; - int (*act)(struct sk_buff **, struct tc_action *, struct tcf_result *); + int (*act)(struct sk_buff *, struct tc_action *, struct tcf_result *); int (*get_stats)(struct sk_buff *, struct tc_action *); int (*dump)(struct sk_buff *, struct tc_action *,int , int); int (*cleanup)(struct tc_action *, int bind); diff --git a/net/sched/act_api.c b/net/sched/act_api.c index 2ce1cb2..bd651a4 100644 --- a/net/sched/act_api.c +++ b/net/sched/act_api.c @@ -165,7 +165,7 @@ int tcf_action_exec(struct sk_buff *skb, struct tc_action *act, while ((a = act) != NULL) { repeat: if (a->ops && a->ops->act) { - ret = a->ops->act(&skb, a, res); + ret = a->ops->act(skb, a, res); if (TC_MUNGED & skb->tc_verd) { /* copied already, allow trampling */ skb->tc_verd = SET_TC_OK2MUNGE(skb->tc_verd); diff --git a/net/sched/gact.c b/net/sched/gact.c index d1c6d54..a1e68f7 100644 --- a/net/sched/gact.c +++ b/net/sched/gact.c @@ -135,10 +135,9 @@ tcf_gact_cleanup(struct tc_action *a, int bind) } static int -tcf_gact(struct sk_buff **pskb, struct tc_action *a, struct tcf_result *res) +tcf_gact(struct sk_buff *skb, struct tc_action *a, struct tcf_result *res) { struct tcf_gact *p = PRIV(a, gact); - struct sk_buff *skb = *pskb; int action = TC_ACT_SHOT; spin_lock(&p->lock); diff --git a/net/sched/ipt.c b/net/sched/ipt.c index f50136e..b500193 100644 --- a/net/sched/ipt.c +++ b/net/sched/ipt.c @@ -201,11 +201,10 @@ tcf_ipt_cleanup(struct tc_action *a, int bind) } static int -tcf_ipt(struct sk_buff **pskb, struct tc_action *a, struct tcf_result *res) +tcf_ipt(struct sk_buff *skb, struct tc_action *a, struct tcf_result *res) { int ret = 0, result = 0; struct tcf_ipt *p = PRIV(a, ipt); - struct sk_buff *skb = *pskb; if (skb_cloned(skb)) { if (pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) @@ -222,6 +221,9 @@ tcf_ipt(struct sk_buff **pskb, struct tc_action *a, struct tcf_result *res) worry later - danger - this API seems to have changed from earlier kernels */ + /* iptables targets take a double skb pointer in case the skb + * needs to be replaced. We don't own the skb, so this must not + * happen. The pskb_expand_head above should make sure of this */ ret = p->t->u.kernel.target->target(&skb, skb->dev, NULL, p->hook, p->t->data, NULL); switch (ret) { diff --git a/net/sched/mirred.c b/net/sched/mirred.c index 20d0691..4fcccbd 100644 --- a/net/sched/mirred.c +++ b/net/sched/mirred.c @@ -158,12 +158,11 @@ tcf_mirred_cleanup(struct tc_action *a, int bind) } static int -tcf_mirred(struct sk_buff **pskb, struct tc_action *a, struct tcf_result *res) +tcf_mirred(struct sk_buff *skb, struct tc_action *a, struct tcf_result *res) { struct tcf_mirred *p = PRIV(a, mirred); struct net_device *dev; struct sk_buff *skb2 = NULL; - struct sk_buff *skb = *pskb; u32 at = G_TC_AT(skb->tc_verd); spin_lock(&p->lock); diff --git a/net/sched/pedit.c b/net/sched/pedit.c index 767d24f..b5167af 100644 --- a/net/sched/pedit.c +++ b/net/sched/pedit.c @@ -130,10 +130,9 @@ tcf_pedit_cleanup(struct tc_action *a, int bind) } static int -tcf_pedit(struct sk_buff **pskb, struct tc_action *a, struct tcf_result *res) +tcf_pedit(struct sk_buff *skb, struct tc_action *a, struct tcf_result *res) { struct tcf_pedit *p = PRIV(a, pedit); - struct sk_buff *skb = *pskb; int i, munged = 0; u8 *pptr; diff --git a/net/sched/police.c b/net/sched/police.c index eb39fb2..a834516 100644 --- a/net/sched/police.c +++ b/net/sched/police.c @@ -284,11 +284,10 @@ static int tcf_act_police_cleanup(struct tc_action *a, int bind) return 0; } -static int tcf_act_police(struct sk_buff **pskb, struct tc_action *a, +static int tcf_act_police(struct sk_buff *skb, struct tc_action *a, struct tcf_result *res) { psched_time_t now; - struct sk_buff *skb = *pskb; struct tcf_police *p = PRIV(a); long toks; long ptoks = 0; diff --git a/net/sched/simple.c b/net/sched/simple.c index 8a6ae4f..e5f2e1f 100644 --- a/net/sched/simple.c +++ b/net/sched/simple.c @@ -44,9 +44,8 @@ static DEFINE_RWLOCK(simp_lock); #include #include -static int tcf_simp(struct sk_buff **pskb, struct tc_action *a, struct tcf_result *res) +static int tcf_simp(struct sk_buff *skb, struct tc_action *a, struct tcf_result *res) { - struct sk_buff *skb = *pskb; struct tcf_defact *p = PRIV(a, defact); spin_lock(&p->lock); -- cgit v1.1 From 31bd06eb33bbabe643385a861d780d950ca73846 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Sun, 8 Jan 2006 22:16:25 -0800 Subject: [PKT_SCHED]: Remove some obsolete policer exports Also make sure the legacy code is only built when CONFIG_NET_CLS_ACT is not set. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/sched/police.c | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/net/sched/police.c b/net/sched/police.c index a834516..fa877f8 100644 --- a/net/sched/police.c +++ b/net/sched/police.c @@ -407,7 +407,7 @@ police_cleanup_module(void) module_init(police_init_module); module_exit(police_cleanup_module); -#endif +#else /* CONFIG_NET_CLS_ACT */ struct tcf_police * tcf_police_locate(struct rtattr *rta, struct rtattr *est) { @@ -544,6 +544,7 @@ int tcf_police(struct sk_buff *skb, struct tcf_police *p) spin_unlock(&p->lock); return p->action; } +EXPORT_SYMBOL(tcf_police); int tcf_police_dump(struct sk_buff *skb, struct tcf_police *p) { @@ -600,13 +601,4 @@ errout: return -1; } - -EXPORT_SYMBOL(tcf_police); -EXPORT_SYMBOL(tcf_police_destroy); -EXPORT_SYMBOL(tcf_police_dump); -EXPORT_SYMBOL(tcf_police_dump_stats); -EXPORT_SYMBOL(tcf_police_hash); -EXPORT_SYMBOL(tcf_police_ht); -EXPORT_SYMBOL(tcf_police_locate); -EXPORT_SYMBOL(tcf_police_lookup); -EXPORT_SYMBOL(tcf_police_new_index); +#endif /* CONFIG_NET_CLS_ACT */ -- cgit v1.1 From 541673c859c0d71dedaaea1c148dfe3ccccc9422 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Sun, 8 Jan 2006 22:17:27 -0800 Subject: [PKT_SCHED]: Fix memory leak when dumping in pedit action Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/sched/pedit.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/sched/pedit.c b/net/sched/pedit.c index b5167af..1742a68 100644 --- a/net/sched/pedit.c +++ b/net/sched/pedit.c @@ -245,10 +245,12 @@ tcf_pedit_dump(struct sk_buff *skb, struct tc_action *a,int bind, int ref) t.lastuse = jiffies_to_clock_t(jiffies - p->tm.lastuse); t.expires = jiffies_to_clock_t(p->tm.expires); RTA_PUT(skb, TCA_PEDIT_TM, sizeof(t), &t); + kfree(opt); return skb->len; rtattr_failure: skb_trim(skb, b - skb->data); + kfree(opt); return -1; } -- cgit v1.1 From 4bba3925924148c24fb0c7636a04ad69a6a56b84 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Sun, 8 Jan 2006 22:22:14 -0800 Subject: [PKT_SCHED]: Prefix tc actions with act_ Clean up the net/sched directory a bit by prefix all actions with act_. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/sched/Makefile | 14 +- net/sched/act_api.c | 2 +- net/sched/act_gact.c | 230 +++++++++++++++++++ net/sched/act_ipt.c | 328 +++++++++++++++++++++++++++ net/sched/act_mirred.c | 275 ++++++++++++++++++++++ net/sched/act_pedit.c | 289 +++++++++++++++++++++++ net/sched/act_police.c | 604 +++++++++++++++++++++++++++++++++++++++++++++++++ net/sched/act_simple.c | 92 ++++++++ net/sched/gact.c | 230 ------------------- net/sched/ipt.c | 328 --------------------------- net/sched/mirred.c | 275 ---------------------- net/sched/pedit.c | 289 ----------------------- net/sched/police.c | 604 ------------------------------------------------- net/sched/simple.c | 92 -------- 14 files changed, 1826 insertions(+), 1826 deletions(-) create mode 100644 net/sched/act_gact.c create mode 100644 net/sched/act_ipt.c create mode 100644 net/sched/act_mirred.c create mode 100644 net/sched/act_pedit.c create mode 100644 net/sched/act_police.c create mode 100644 net/sched/act_simple.c delete mode 100644 net/sched/gact.c delete mode 100644 net/sched/ipt.c delete mode 100644 net/sched/mirred.c delete mode 100644 net/sched/pedit.c delete mode 100644 net/sched/police.c delete mode 100644 net/sched/simple.c diff --git a/net/sched/Makefile b/net/sched/Makefile index e48d0d4..0f06aec 100644 --- a/net/sched/Makefile +++ b/net/sched/Makefile @@ -7,13 +7,13 @@ obj-y := sch_generic.o obj-$(CONFIG_NET_SCHED) += sch_api.o sch_fifo.o sch_blackhole.o obj-$(CONFIG_NET_CLS) += cls_api.o obj-$(CONFIG_NET_CLS_ACT) += act_api.o -obj-$(CONFIG_NET_ACT_POLICE) += police.o -obj-$(CONFIG_NET_CLS_POLICE) += police.o -obj-$(CONFIG_NET_ACT_GACT) += gact.o -obj-$(CONFIG_NET_ACT_MIRRED) += mirred.o -obj-$(CONFIG_NET_ACT_IPT) += ipt.o -obj-$(CONFIG_NET_ACT_PEDIT) += pedit.o -obj-$(CONFIG_NET_ACT_SIMP) += simple.o +obj-$(CONFIG_NET_ACT_POLICE) += act_police.o +obj-$(CONFIG_NET_CLS_POLICE) += act_police.o +obj-$(CONFIG_NET_ACT_GACT) += act_gact.o +obj-$(CONFIG_NET_ACT_MIRRED) += act_mirred.o +obj-$(CONFIG_NET_ACT_IPT) += act_ipt.o +obj-$(CONFIG_NET_ACT_PEDIT) += act_pedit.o +obj-$(CONFIG_NET_ACT_SIMP) += act_simple.o obj-$(CONFIG_NET_SCH_CBQ) += sch_cbq.o obj-$(CONFIG_NET_SCH_HTB) += sch_htb.o obj-$(CONFIG_NET_SCH_HPFQ) += sch_hpfq.o diff --git a/net/sched/act_api.c b/net/sched/act_api.c index bd651a4..792ce59 100644 --- a/net/sched/act_api.c +++ b/net/sched/act_api.c @@ -290,7 +290,7 @@ struct tc_action *tcf_action_init_1(struct rtattr *rta, struct rtattr *est, if (a_o == NULL) { #ifdef CONFIG_KMOD rtnl_unlock(); - request_module(act_name); + request_module("act_%s", act_name); rtnl_lock(); a_o = tc_lookup_action_n(act_name); diff --git a/net/sched/act_gact.c b/net/sched/act_gact.c new file mode 100644 index 0000000..a1e68f7 --- /dev/null +++ b/net/sched/act_gact.c @@ -0,0 +1,230 @@ +/* + * net/sched/gact.c Generic actions + * + * 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 (at your option) any later version. + * + * copyright Jamal Hadi Salim (2002-4) + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* use generic hash table */ +#define MY_TAB_SIZE 16 +#define MY_TAB_MASK 15 + +static u32 idx_gen; +static struct tcf_gact *tcf_gact_ht[MY_TAB_SIZE]; +static DEFINE_RWLOCK(gact_lock); + +/* ovewrride the defaults */ +#define tcf_st tcf_gact +#define tc_st tc_gact +#define tcf_t_lock gact_lock +#define tcf_ht tcf_gact_ht + +#define CONFIG_NET_ACT_INIT 1 +#include + +#ifdef CONFIG_GACT_PROB +static int gact_net_rand(struct tcf_gact *p) +{ + if (net_random()%p->pval) + return p->action; + return p->paction; +} + +static int gact_determ(struct tcf_gact *p) +{ + if (p->bstats.packets%p->pval) + return p->action; + return p->paction; +} + +typedef int (*g_rand)(struct tcf_gact *p); +static g_rand gact_rand[MAX_RAND]= { NULL, gact_net_rand, gact_determ }; +#endif + +static int tcf_gact_init(struct rtattr *rta, struct rtattr *est, + struct tc_action *a, int ovr, int bind) +{ + struct rtattr *tb[TCA_GACT_MAX]; + struct tc_gact *parm; + struct tcf_gact *p; + int ret = 0; + + if (rta == NULL || rtattr_parse_nested(tb, TCA_GACT_MAX, rta) < 0) + return -EINVAL; + + if (tb[TCA_GACT_PARMS - 1] == NULL || + RTA_PAYLOAD(tb[TCA_GACT_PARMS - 1]) < sizeof(*parm)) + return -EINVAL; + parm = RTA_DATA(tb[TCA_GACT_PARMS - 1]); + + if (tb[TCA_GACT_PROB-1] != NULL) +#ifdef CONFIG_GACT_PROB + if (RTA_PAYLOAD(tb[TCA_GACT_PROB-1]) < sizeof(struct tc_gact_p)) + return -EINVAL; +#else + return -EOPNOTSUPP; +#endif + + p = tcf_hash_check(parm->index, a, ovr, bind); + if (p == NULL) { + p = tcf_hash_create(parm->index, est, a, sizeof(*p), ovr, bind); + if (p == NULL) + return -ENOMEM; + ret = ACT_P_CREATED; + } else { + if (!ovr) { + tcf_hash_release(p, bind); + return -EEXIST; + } + } + + spin_lock_bh(&p->lock); + p->action = parm->action; +#ifdef CONFIG_GACT_PROB + if (tb[TCA_GACT_PROB-1] != NULL) { + struct tc_gact_p *p_parm = RTA_DATA(tb[TCA_GACT_PROB-1]); + p->paction = p_parm->paction; + p->pval = p_parm->pval; + p->ptype = p_parm->ptype; + } +#endif + spin_unlock_bh(&p->lock); + if (ret == ACT_P_CREATED) + tcf_hash_insert(p); + return ret; +} + +static int +tcf_gact_cleanup(struct tc_action *a, int bind) +{ + struct tcf_gact *p = PRIV(a, gact); + + if (p != NULL) + return tcf_hash_release(p, bind); + return 0; +} + +static int +tcf_gact(struct sk_buff *skb, struct tc_action *a, struct tcf_result *res) +{ + struct tcf_gact *p = PRIV(a, gact); + int action = TC_ACT_SHOT; + + spin_lock(&p->lock); +#ifdef CONFIG_GACT_PROB + if (p->ptype && gact_rand[p->ptype] != NULL) + action = gact_rand[p->ptype](p); + else + action = p->action; +#else + action = p->action; +#endif + p->bstats.bytes += skb->len; + p->bstats.packets++; + if (action == TC_ACT_SHOT) + p->qstats.drops++; + p->tm.lastuse = jiffies; + spin_unlock(&p->lock); + + return action; +} + +static int +tcf_gact_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref) +{ + unsigned char *b = skb->tail; + struct tc_gact opt; + struct tcf_gact *p = PRIV(a, gact); + struct tcf_t t; + + opt.index = p->index; + opt.refcnt = p->refcnt - ref; + opt.bindcnt = p->bindcnt - bind; + opt.action = p->action; + RTA_PUT(skb, TCA_GACT_PARMS, sizeof(opt), &opt); +#ifdef CONFIG_GACT_PROB + if (p->ptype) { + struct tc_gact_p p_opt; + p_opt.paction = p->paction; + p_opt.pval = p->pval; + p_opt.ptype = p->ptype; + RTA_PUT(skb, TCA_GACT_PROB, sizeof(p_opt), &p_opt); + } +#endif + t.install = jiffies_to_clock_t(jiffies - p->tm.install); + t.lastuse = jiffies_to_clock_t(jiffies - p->tm.lastuse); + t.expires = jiffies_to_clock_t(p->tm.expires); + RTA_PUT(skb, TCA_GACT_TM, sizeof(t), &t); + return skb->len; + + rtattr_failure: + skb_trim(skb, b - skb->data); + return -1; +} + +static struct tc_action_ops act_gact_ops = { + .kind = "gact", + .type = TCA_ACT_GACT, + .capab = TCA_CAP_NONE, + .owner = THIS_MODULE, + .act = tcf_gact, + .dump = tcf_gact_dump, + .cleanup = tcf_gact_cleanup, + .lookup = tcf_hash_search, + .init = tcf_gact_init, + .walk = tcf_generic_walker +}; + +MODULE_AUTHOR("Jamal Hadi Salim(2002-4)"); +MODULE_DESCRIPTION("Generic Classifier actions"); +MODULE_LICENSE("GPL"); + +static int __init +gact_init_module(void) +{ +#ifdef CONFIG_GACT_PROB + printk("GACT probability on\n"); +#else + printk("GACT probability NOT on\n"); +#endif + return tcf_register_action(&act_gact_ops); +} + +static void __exit +gact_cleanup_module(void) +{ + tcf_unregister_action(&act_gact_ops); +} + +module_init(gact_init_module); +module_exit(gact_cleanup_module); diff --git a/net/sched/act_ipt.c b/net/sched/act_ipt.c new file mode 100644 index 0000000..b500193 --- /dev/null +++ b/net/sched/act_ipt.c @@ -0,0 +1,328 @@ +/* + * net/sched/ipt.c iptables target interface + * + *TODO: Add other tables. For now we only support the ipv4 table targets + * + * 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 (at your option) any later version. + * + * Copyright: Jamal Hadi Salim (2002-4) + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* use generic hash table */ +#define MY_TAB_SIZE 16 +#define MY_TAB_MASK 15 + +static u32 idx_gen; +static struct tcf_ipt *tcf_ipt_ht[MY_TAB_SIZE]; +/* ipt hash table lock */ +static DEFINE_RWLOCK(ipt_lock); + +/* ovewrride the defaults */ +#define tcf_st tcf_ipt +#define tcf_t_lock ipt_lock +#define tcf_ht tcf_ipt_ht + +#define CONFIG_NET_ACT_INIT +#include + +static int +ipt_init_target(struct ipt_entry_target *t, char *table, unsigned int hook) +{ + struct ipt_target *target; + int ret = 0; + + target = ipt_find_target(t->u.user.name, t->u.user.revision); + if (!target) + return -ENOENT; + + DPRINTK("ipt_init_target: found %s\n", target->name); + t->u.kernel.target = target; + + if (t->u.kernel.target->checkentry + && !t->u.kernel.target->checkentry(table, NULL, t->data, + t->u.target_size - sizeof(*t), + hook)) { + DPRINTK("ipt_init_target: check failed for `%s'.\n", + t->u.kernel.target->name); + module_put(t->u.kernel.target->me); + ret = -EINVAL; + } + + return ret; +} + +static void +ipt_destroy_target(struct ipt_entry_target *t) +{ + if (t->u.kernel.target->destroy) + t->u.kernel.target->destroy(t->data, + t->u.target_size - sizeof(*t)); + module_put(t->u.kernel.target->me); +} + +static int +tcf_ipt_release(struct tcf_ipt *p, int bind) +{ + int ret = 0; + if (p) { + if (bind) + p->bindcnt--; + p->refcnt--; + if (p->bindcnt <= 0 && p->refcnt <= 0) { + ipt_destroy_target(p->t); + kfree(p->tname); + kfree(p->t); + tcf_hash_destroy(p); + ret = ACT_P_DELETED; + } + } + return ret; +} + +static int +tcf_ipt_init(struct rtattr *rta, struct rtattr *est, struct tc_action *a, + int ovr, int bind) +{ + struct rtattr *tb[TCA_IPT_MAX]; + struct tcf_ipt *p; + struct ipt_entry_target *td, *t; + char *tname; + int ret = 0, err; + u32 hook = 0; + u32 index = 0; + + if (rta == NULL || rtattr_parse_nested(tb, TCA_IPT_MAX, rta) < 0) + return -EINVAL; + + if (tb[TCA_IPT_HOOK-1] == NULL || + RTA_PAYLOAD(tb[TCA_IPT_HOOK-1]) < sizeof(u32)) + return -EINVAL; + if (tb[TCA_IPT_TARG-1] == NULL || + RTA_PAYLOAD(tb[TCA_IPT_TARG-1]) < sizeof(*t)) + return -EINVAL; + td = (struct ipt_entry_target *)RTA_DATA(tb[TCA_IPT_TARG-1]); + if (RTA_PAYLOAD(tb[TCA_IPT_TARG-1]) < td->u.target_size) + return -EINVAL; + + if (tb[TCA_IPT_INDEX-1] != NULL && + RTA_PAYLOAD(tb[TCA_IPT_INDEX-1]) >= sizeof(u32)) + index = *(u32 *)RTA_DATA(tb[TCA_IPT_INDEX-1]); + + p = tcf_hash_check(index, a, ovr, bind); + if (p == NULL) { + p = tcf_hash_create(index, est, a, sizeof(*p), ovr, bind); + if (p == NULL) + return -ENOMEM; + ret = ACT_P_CREATED; + } else { + if (!ovr) { + tcf_ipt_release(p, bind); + return -EEXIST; + } + } + + hook = *(u32 *)RTA_DATA(tb[TCA_IPT_HOOK-1]); + + err = -ENOMEM; + tname = kmalloc(IFNAMSIZ, GFP_KERNEL); + if (tname == NULL) + goto err1; + if (tb[TCA_IPT_TABLE - 1] == NULL || + rtattr_strlcpy(tname, tb[TCA_IPT_TABLE-1], IFNAMSIZ) >= IFNAMSIZ) + strcpy(tname, "mangle"); + + t = kmalloc(td->u.target_size, GFP_KERNEL); + if (t == NULL) + goto err2; + memcpy(t, td, td->u.target_size); + + if ((err = ipt_init_target(t, tname, hook)) < 0) + goto err3; + + spin_lock_bh(&p->lock); + if (ret != ACT_P_CREATED) { + ipt_destroy_target(p->t); + kfree(p->tname); + kfree(p->t); + } + p->tname = tname; + p->t = t; + p->hook = hook; + spin_unlock_bh(&p->lock); + if (ret == ACT_P_CREATED) + tcf_hash_insert(p); + return ret; + +err3: + kfree(t); +err2: + kfree(tname); +err1: + kfree(p); + return err; +} + +static int +tcf_ipt_cleanup(struct tc_action *a, int bind) +{ + struct tcf_ipt *p = PRIV(a, ipt); + return tcf_ipt_release(p, bind); +} + +static int +tcf_ipt(struct sk_buff *skb, struct tc_action *a, struct tcf_result *res) +{ + int ret = 0, result = 0; + struct tcf_ipt *p = PRIV(a, ipt); + + if (skb_cloned(skb)) { + if (pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) + return TC_ACT_UNSPEC; + } + + spin_lock(&p->lock); + + p->tm.lastuse = jiffies; + p->bstats.bytes += skb->len; + p->bstats.packets++; + + /* yes, we have to worry about both in and out dev + worry later - danger - this API seems to have changed + from earlier kernels */ + + /* iptables targets take a double skb pointer in case the skb + * needs to be replaced. We don't own the skb, so this must not + * happen. The pskb_expand_head above should make sure of this */ + ret = p->t->u.kernel.target->target(&skb, skb->dev, NULL, + p->hook, p->t->data, NULL); + switch (ret) { + case NF_ACCEPT: + result = TC_ACT_OK; + break; + case NF_DROP: + result = TC_ACT_SHOT; + p->qstats.drops++; + break; + case IPT_CONTINUE: + result = TC_ACT_PIPE; + break; + default: + if (net_ratelimit()) + printk("Bogus netfilter code %d assume ACCEPT\n", ret); + result = TC_POLICE_OK; + break; + } + spin_unlock(&p->lock); + return result; + +} + +static int +tcf_ipt_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref) +{ + struct ipt_entry_target *t; + struct tcf_t tm; + struct tc_cnt c; + unsigned char *b = skb->tail; + struct tcf_ipt *p = PRIV(a, ipt); + + /* for simple targets kernel size == user size + ** user name = target name + ** for foolproof you need to not assume this + */ + + t = kmalloc(p->t->u.user.target_size, GFP_ATOMIC); + if (t == NULL) + goto rtattr_failure; + + c.bindcnt = p->bindcnt - bind; + c.refcnt = p->refcnt - ref; + memcpy(t, p->t, p->t->u.user.target_size); + strcpy(t->u.user.name, p->t->u.kernel.target->name); + + DPRINTK("\ttcf_ipt_dump tablename %s length %d\n", p->tname, + strlen(p->tname)); + DPRINTK("\tdump target name %s size %d size user %d " + "data[0] %x data[1] %x\n", p->t->u.kernel.target->name, + p->t->u.target_size, p->t->u.user.target_size, + p->t->data[0], p->t->data[1]); + RTA_PUT(skb, TCA_IPT_TARG, p->t->u.user.target_size, t); + RTA_PUT(skb, TCA_IPT_INDEX, 4, &p->index); + RTA_PUT(skb, TCA_IPT_HOOK, 4, &p->hook); + RTA_PUT(skb, TCA_IPT_CNT, sizeof(struct tc_cnt), &c); + RTA_PUT(skb, TCA_IPT_TABLE, IFNAMSIZ, p->tname); + tm.install = jiffies_to_clock_t(jiffies - p->tm.install); + tm.lastuse = jiffies_to_clock_t(jiffies - p->tm.lastuse); + tm.expires = jiffies_to_clock_t(p->tm.expires); + RTA_PUT(skb, TCA_IPT_TM, sizeof (tm), &tm); + kfree(t); + return skb->len; + + rtattr_failure: + skb_trim(skb, b - skb->data); + kfree(t); + return -1; +} + +static struct tc_action_ops act_ipt_ops = { + .kind = "ipt", + .type = TCA_ACT_IPT, + .capab = TCA_CAP_NONE, + .owner = THIS_MODULE, + .act = tcf_ipt, + .dump = tcf_ipt_dump, + .cleanup = tcf_ipt_cleanup, + .lookup = tcf_hash_search, + .init = tcf_ipt_init, + .walk = tcf_generic_walker +}; + +MODULE_AUTHOR("Jamal Hadi Salim(2002-4)"); +MODULE_DESCRIPTION("Iptables target actions"); +MODULE_LICENSE("GPL"); + +static int __init +ipt_init_module(void) +{ + return tcf_register_action(&act_ipt_ops); +} + +static void __exit +ipt_cleanup_module(void) +{ + tcf_unregister_action(&act_ipt_ops); +} + +module_init(ipt_init_module); +module_exit(ipt_cleanup_module); diff --git a/net/sched/act_mirred.c b/net/sched/act_mirred.c new file mode 100644 index 0000000..4fcccbd --- /dev/null +++ b/net/sched/act_mirred.c @@ -0,0 +1,275 @@ +/* + * net/sched/mirred.c packet mirroring and redirect actions + * + * 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 (at your option) any later version. + * + * Authors: Jamal Hadi Salim (2002-4) + * + * TODO: Add ingress support (and socket redirect support) + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + + +/* use generic hash table */ +#define MY_TAB_SIZE 8 +#define MY_TAB_MASK (MY_TAB_SIZE - 1) +static u32 idx_gen; +static struct tcf_mirred *tcf_mirred_ht[MY_TAB_SIZE]; +static DEFINE_RWLOCK(mirred_lock); + +/* ovewrride the defaults */ +#define tcf_st tcf_mirred +#define tc_st tc_mirred +#define tcf_t_lock mirred_lock +#define tcf_ht tcf_mirred_ht + +#define CONFIG_NET_ACT_INIT 1 +#include + +static inline int +tcf_mirred_release(struct tcf_mirred *p, int bind) +{ + if (p) { + if (bind) + p->bindcnt--; + p->refcnt--; + if(!p->bindcnt && p->refcnt <= 0) { + dev_put(p->dev); + tcf_hash_destroy(p); + return 1; + } + } + return 0; +} + +static int +tcf_mirred_init(struct rtattr *rta, struct rtattr *est, struct tc_action *a, + int ovr, int bind) +{ + struct rtattr *tb[TCA_MIRRED_MAX]; + struct tc_mirred *parm; + struct tcf_mirred *p; + struct net_device *dev = NULL; + int ret = 0; + int ok_push = 0; + + if (rta == NULL || rtattr_parse_nested(tb, TCA_MIRRED_MAX, rta) < 0) + return -EINVAL; + + if (tb[TCA_MIRRED_PARMS-1] == NULL || + RTA_PAYLOAD(tb[TCA_MIRRED_PARMS-1]) < sizeof(*parm)) + return -EINVAL; + parm = RTA_DATA(tb[TCA_MIRRED_PARMS-1]); + + if (parm->ifindex) { + dev = __dev_get_by_index(parm->ifindex); + if (dev == NULL) + return -ENODEV; + switch (dev->type) { + case ARPHRD_TUNNEL: + case ARPHRD_TUNNEL6: + case ARPHRD_SIT: + case ARPHRD_IPGRE: + case ARPHRD_VOID: + case ARPHRD_NONE: + ok_push = 0; + break; + default: + ok_push = 1; + break; + } + } + + p = tcf_hash_check(parm->index, a, ovr, bind); + if (p == NULL) { + if (!parm->ifindex) + return -EINVAL; + p = tcf_hash_create(parm->index, est, a, sizeof(*p), ovr, bind); + if (p == NULL) + return -ENOMEM; + ret = ACT_P_CREATED; + } else { + if (!ovr) { + tcf_mirred_release(p, bind); + return -EEXIST; + } + } + + spin_lock_bh(&p->lock); + p->action = parm->action; + p->eaction = parm->eaction; + if (parm->ifindex) { + p->ifindex = parm->ifindex; + if (ret != ACT_P_CREATED) + dev_put(p->dev); + p->dev = dev; + dev_hold(dev); + p->ok_push = ok_push; + } + spin_unlock_bh(&p->lock); + if (ret == ACT_P_CREATED) + tcf_hash_insert(p); + + DPRINTK("tcf_mirred_init index %d action %d eaction %d device %s " + "ifindex %d\n", parm->index, parm->action, parm->eaction, + dev->name, parm->ifindex); + return ret; +} + +static int +tcf_mirred_cleanup(struct tc_action *a, int bind) +{ + struct tcf_mirred *p = PRIV(a, mirred); + + if (p != NULL) + return tcf_mirred_release(p, bind); + return 0; +} + +static int +tcf_mirred(struct sk_buff *skb, struct tc_action *a, struct tcf_result *res) +{ + struct tcf_mirred *p = PRIV(a, mirred); + struct net_device *dev; + struct sk_buff *skb2 = NULL; + u32 at = G_TC_AT(skb->tc_verd); + + spin_lock(&p->lock); + + dev = p->dev; + p->tm.lastuse = jiffies; + + if (!(dev->flags&IFF_UP) ) { + if (net_ratelimit()) + printk("mirred to Houston: device %s is gone!\n", + dev->name); +bad_mirred: + if (skb2 != NULL) + kfree_skb(skb2); + p->qstats.overlimits++; + p->bstats.bytes += skb->len; + p->bstats.packets++; + spin_unlock(&p->lock); + /* should we be asking for packet to be dropped? + * may make sense for redirect case only + */ + return TC_ACT_SHOT; + } + + skb2 = skb_clone(skb, GFP_ATOMIC); + if (skb2 == NULL) + goto bad_mirred; + if (p->eaction != TCA_EGRESS_MIRROR && p->eaction != TCA_EGRESS_REDIR) { + if (net_ratelimit()) + printk("tcf_mirred unknown action %d\n", p->eaction); + goto bad_mirred; + } + + p->bstats.bytes += skb2->len; + p->bstats.packets++; + if (!(at & AT_EGRESS)) + if (p->ok_push) + skb_push(skb2, skb2->dev->hard_header_len); + + /* mirror is always swallowed */ + if (p->eaction != TCA_EGRESS_MIRROR) + skb2->tc_verd = SET_TC_FROM(skb2->tc_verd, at); + + skb2->dev = dev; + skb2->input_dev = skb->dev; + dev_queue_xmit(skb2); + spin_unlock(&p->lock); + return p->action; +} + +static int +tcf_mirred_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref) +{ + unsigned char *b = skb->tail; + struct tc_mirred opt; + struct tcf_mirred *p = PRIV(a, mirred); + struct tcf_t t; + + opt.index = p->index; + opt.action = p->action; + opt.refcnt = p->refcnt - ref; + opt.bindcnt = p->bindcnt - bind; + opt.eaction = p->eaction; + opt.ifindex = p->ifindex; + DPRINTK("tcf_mirred_dump index %d action %d eaction %d ifindex %d\n", + p->index, p->action, p->eaction, p->ifindex); + RTA_PUT(skb, TCA_MIRRED_PARMS, sizeof(opt), &opt); + t.install = jiffies_to_clock_t(jiffies - p->tm.install); + t.lastuse = jiffies_to_clock_t(jiffies - p->tm.lastuse); + t.expires = jiffies_to_clock_t(p->tm.expires); + RTA_PUT(skb, TCA_MIRRED_TM, sizeof(t), &t); + return skb->len; + + rtattr_failure: + skb_trim(skb, b - skb->data); + return -1; +} + +static struct tc_action_ops act_mirred_ops = { + .kind = "mirred", + .type = TCA_ACT_MIRRED, + .capab = TCA_CAP_NONE, + .owner = THIS_MODULE, + .act = tcf_mirred, + .dump = tcf_mirred_dump, + .cleanup = tcf_mirred_cleanup, + .lookup = tcf_hash_search, + .init = tcf_mirred_init, + .walk = tcf_generic_walker +}; + +MODULE_AUTHOR("Jamal Hadi Salim(2002)"); +MODULE_DESCRIPTION("Device Mirror/redirect actions"); +MODULE_LICENSE("GPL"); + +static int __init +mirred_init_module(void) +{ + printk("Mirror/redirect action on\n"); + return tcf_register_action(&act_mirred_ops); +} + +static void __exit +mirred_cleanup_module(void) +{ + tcf_unregister_action(&act_mirred_ops); +} + +module_init(mirred_init_module); +module_exit(mirred_cleanup_module); diff --git a/net/sched/act_pedit.c b/net/sched/act_pedit.c new file mode 100644 index 0000000..1742a68 --- /dev/null +++ b/net/sched/act_pedit.c @@ -0,0 +1,289 @@ +/* + * net/sched/pedit.c Generic packet editor + * + * 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 (at your option) any later version. + * + * Authors: Jamal Hadi Salim (2002-4) + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define PEDIT_DEB 1 + +/* use generic hash table */ +#define MY_TAB_SIZE 16 +#define MY_TAB_MASK 15 +static u32 idx_gen; +static struct tcf_pedit *tcf_pedit_ht[MY_TAB_SIZE]; +static DEFINE_RWLOCK(pedit_lock); + +#define tcf_st tcf_pedit +#define tc_st tc_pedit +#define tcf_t_lock pedit_lock +#define tcf_ht tcf_pedit_ht + +#define CONFIG_NET_ACT_INIT 1 +#include + +static int +tcf_pedit_init(struct rtattr *rta, struct rtattr *est, struct tc_action *a, + int ovr, int bind) +{ + struct rtattr *tb[TCA_PEDIT_MAX]; + struct tc_pedit *parm; + int ret = 0; + struct tcf_pedit *p; + struct tc_pedit_key *keys = NULL; + int ksize; + + if (rta == NULL || rtattr_parse_nested(tb, TCA_PEDIT_MAX, rta) < 0) + return -EINVAL; + + if (tb[TCA_PEDIT_PARMS - 1] == NULL || + RTA_PAYLOAD(tb[TCA_PEDIT_PARMS-1]) < sizeof(*parm)) + return -EINVAL; + parm = RTA_DATA(tb[TCA_PEDIT_PARMS-1]); + ksize = parm->nkeys * sizeof(struct tc_pedit_key); + if (RTA_PAYLOAD(tb[TCA_PEDIT_PARMS-1]) < sizeof(*parm) + ksize) + return -EINVAL; + + p = tcf_hash_check(parm->index, a, ovr, bind); + if (p == NULL) { + if (!parm->nkeys) + return -EINVAL; + p = tcf_hash_create(parm->index, est, a, sizeof(*p), ovr, bind); + if (p == NULL) + return -ENOMEM; + keys = kmalloc(ksize, GFP_KERNEL); + if (keys == NULL) { + kfree(p); + return -ENOMEM; + } + ret = ACT_P_CREATED; + } else { + if (!ovr) { + tcf_hash_release(p, bind); + return -EEXIST; + } + if (p->nkeys && p->nkeys != parm->nkeys) { + keys = kmalloc(ksize, GFP_KERNEL); + if (keys == NULL) + return -ENOMEM; + } + } + + spin_lock_bh(&p->lock); + p->flags = parm->flags; + p->action = parm->action; + if (keys) { + kfree(p->keys); + p->keys = keys; + p->nkeys = parm->nkeys; + } + memcpy(p->keys, parm->keys, ksize); + spin_unlock_bh(&p->lock); + if (ret == ACT_P_CREATED) + tcf_hash_insert(p); + return ret; +} + +static int +tcf_pedit_cleanup(struct tc_action *a, int bind) +{ + struct tcf_pedit *p = PRIV(a, pedit); + + if (p != NULL) { + struct tc_pedit_key *keys = p->keys; + if (tcf_hash_release(p, bind)) { + kfree(keys); + return 1; + } + } + return 0; +} + +static int +tcf_pedit(struct sk_buff *skb, struct tc_action *a, struct tcf_result *res) +{ + struct tcf_pedit *p = PRIV(a, pedit); + int i, munged = 0; + u8 *pptr; + + if (!(skb->tc_verd & TC_OK2MUNGE)) { + /* should we set skb->cloned? */ + if (pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) { + return p->action; + } + } + + pptr = skb->nh.raw; + + spin_lock(&p->lock); + + p->tm.lastuse = jiffies; + + if (p->nkeys > 0) { + struct tc_pedit_key *tkey = p->keys; + + for (i = p->nkeys; i > 0; i--, tkey++) { + u32 *ptr; + int offset = tkey->off; + + if (tkey->offmask) { + if (skb->len > tkey->at) { + char *j = pptr + tkey->at; + offset += ((*j & tkey->offmask) >> + tkey->shift); + } else { + goto bad; + } + } + + if (offset % 4) { + printk("offset must be on 32 bit boundaries\n"); + goto bad; + } + if (skb->len < 0 || (offset > 0 && offset > skb->len)) { + printk("offset %d cant exceed pkt length %d\n", + offset, skb->len); + goto bad; + } + + ptr = (u32 *)(pptr+offset); + /* just do it, baby */ + *ptr = ((*ptr & tkey->mask) ^ tkey->val); + munged++; + } + + if (munged) + skb->tc_verd = SET_TC_MUNGED(skb->tc_verd); + goto done; + } else { + printk("pedit BUG: index %d\n",p->index); + } + +bad: + p->qstats.overlimits++; +done: + p->bstats.bytes += skb->len; + p->bstats.packets++; + spin_unlock(&p->lock); + return p->action; +} + +static int +tcf_pedit_dump(struct sk_buff *skb, struct tc_action *a,int bind, int ref) +{ + unsigned char *b = skb->tail; + struct tc_pedit *opt; + struct tcf_pedit *p = PRIV(a, pedit); + struct tcf_t t; + int s; + + s = sizeof(*opt) + p->nkeys * sizeof(struct tc_pedit_key); + + /* netlink spinlocks held above us - must use ATOMIC */ + opt = kmalloc(s, GFP_ATOMIC); + if (opt == NULL) + return -ENOBUFS; + memset(opt, 0, s); + + memcpy(opt->keys, p->keys, p->nkeys * sizeof(struct tc_pedit_key)); + opt->index = p->index; + opt->nkeys = p->nkeys; + opt->flags = p->flags; + opt->action = p->action; + opt->refcnt = p->refcnt - ref; + opt->bindcnt = p->bindcnt - bind; + + +#ifdef PEDIT_DEB + { + /* Debug - get rid of later */ + int i; + struct tc_pedit_key *key = opt->keys; + + for (i=0; inkeys; i++, key++) { + printk( "\n key #%d",i); + printk( " at %d: val %08x mask %08x", + (unsigned int)key->off, + (unsigned int)key->val, + (unsigned int)key->mask); + } + } +#endif + + RTA_PUT(skb, TCA_PEDIT_PARMS, s, opt); + t.install = jiffies_to_clock_t(jiffies - p->tm.install); + t.lastuse = jiffies_to_clock_t(jiffies - p->tm.lastuse); + t.expires = jiffies_to_clock_t(p->tm.expires); + RTA_PUT(skb, TCA_PEDIT_TM, sizeof(t), &t); + kfree(opt); + return skb->len; + +rtattr_failure: + skb_trim(skb, b - skb->data); + kfree(opt); + return -1; +} + +static +struct tc_action_ops act_pedit_ops = { + .kind = "pedit", + .type = TCA_ACT_PEDIT, + .capab = TCA_CAP_NONE, + .owner = THIS_MODULE, + .act = tcf_pedit, + .dump = tcf_pedit_dump, + .cleanup = tcf_pedit_cleanup, + .lookup = tcf_hash_search, + .init = tcf_pedit_init, + .walk = tcf_generic_walker +}; + +MODULE_AUTHOR("Jamal Hadi Salim(2002-4)"); +MODULE_DESCRIPTION("Generic Packet Editor actions"); +MODULE_LICENSE("GPL"); + +static int __init +pedit_init_module(void) +{ + return tcf_register_action(&act_pedit_ops); +} + +static void __exit +pedit_cleanup_module(void) +{ + tcf_unregister_action(&act_pedit_ops); +} + +module_init(pedit_init_module); +module_exit(pedit_cleanup_module); + diff --git a/net/sched/act_police.c b/net/sched/act_police.c new file mode 100644 index 0000000..fa877f8 --- /dev/null +++ b/net/sched/act_police.c @@ -0,0 +1,604 @@ +/* + * net/sched/police.c Input police filter. + * + * 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 (at your option) any later version. + * + * Authors: Alexey Kuznetsov, + * J Hadi Salim (action changes) + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define L2T(p,L) ((p)->R_tab->data[(L)>>(p)->R_tab->rate.cell_log]) +#define L2T_P(p,L) ((p)->P_tab->data[(L)>>(p)->P_tab->rate.cell_log]) +#define PRIV(a) ((struct tcf_police *) (a)->priv) + +/* use generic hash table */ +#define MY_TAB_SIZE 16 +#define MY_TAB_MASK 15 +static u32 idx_gen; +static struct tcf_police *tcf_police_ht[MY_TAB_SIZE]; +/* Policer hash table lock */ +static DEFINE_RWLOCK(police_lock); + +/* Each policer is serialized by its individual spinlock */ + +static __inline__ unsigned tcf_police_hash(u32 index) +{ + return index&0xF; +} + +static __inline__ struct tcf_police * tcf_police_lookup(u32 index) +{ + struct tcf_police *p; + + read_lock(&police_lock); + for (p = tcf_police_ht[tcf_police_hash(index)]; p; p = p->next) { + if (p->index == index) + break; + } + read_unlock(&police_lock); + return p; +} + +#ifdef CONFIG_NET_CLS_ACT +static int tcf_generic_walker(struct sk_buff *skb, struct netlink_callback *cb, + int type, struct tc_action *a) +{ + struct tcf_police *p; + int err = 0, index = -1, i = 0, s_i = 0, n_i = 0; + struct rtattr *r; + + read_lock(&police_lock); + + s_i = cb->args[0]; + + for (i = 0; i < MY_TAB_SIZE; i++) { + p = tcf_police_ht[tcf_police_hash(i)]; + + for (; p; p = p->next) { + index++; + if (index < s_i) + continue; + a->priv = p; + a->order = index; + r = (struct rtattr*) skb->tail; + RTA_PUT(skb, a->order, 0, NULL); + if (type == RTM_DELACTION) + err = tcf_action_dump_1(skb, a, 0, 1); + else + err = tcf_action_dump_1(skb, a, 0, 0); + if (err < 0) { + index--; + skb_trim(skb, (u8*)r - skb->data); + goto done; + } + r->rta_len = skb->tail - (u8*)r; + n_i++; + } + } +done: + read_unlock(&police_lock); + if (n_i) + cb->args[0] += n_i; + return n_i; + +rtattr_failure: + skb_trim(skb, (u8*)r - skb->data); + goto done; +} + +static inline int +tcf_hash_search(struct tc_action *a, u32 index) +{ + struct tcf_police *p = tcf_police_lookup(index); + + if (p != NULL) { + a->priv = p; + return 1; + } else { + return 0; + } +} +#endif + +static inline u32 tcf_police_new_index(void) +{ + do { + if (++idx_gen == 0) + idx_gen = 1; + } while (tcf_police_lookup(idx_gen)); + + return idx_gen; +} + +void tcf_police_destroy(struct tcf_police *p) +{ + unsigned h = tcf_police_hash(p->index); + struct tcf_police **p1p; + + for (p1p = &tcf_police_ht[h]; *p1p; p1p = &(*p1p)->next) { + if (*p1p == p) { + write_lock_bh(&police_lock); + *p1p = p->next; + write_unlock_bh(&police_lock); +#ifdef CONFIG_NET_ESTIMATOR + gen_kill_estimator(&p->bstats, &p->rate_est); +#endif + if (p->R_tab) + qdisc_put_rtab(p->R_tab); + if (p->P_tab) + qdisc_put_rtab(p->P_tab); + kfree(p); + return; + } + } + BUG_TRAP(0); +} + +#ifdef CONFIG_NET_CLS_ACT +static int tcf_act_police_locate(struct rtattr *rta, struct rtattr *est, + struct tc_action *a, int ovr, int bind) +{ + unsigned h; + int ret = 0, err; + struct rtattr *tb[TCA_POLICE_MAX]; + struct tc_police *parm; + struct tcf_police *p; + struct qdisc_rate_table *R_tab = NULL, *P_tab = NULL; + + if (rta == NULL || rtattr_parse_nested(tb, TCA_POLICE_MAX, rta) < 0) + return -EINVAL; + + if (tb[TCA_POLICE_TBF-1] == NULL || + RTA_PAYLOAD(tb[TCA_POLICE_TBF-1]) != sizeof(*parm)) + return -EINVAL; + parm = RTA_DATA(tb[TCA_POLICE_TBF-1]); + + if (tb[TCA_POLICE_RESULT-1] != NULL && + RTA_PAYLOAD(tb[TCA_POLICE_RESULT-1]) != sizeof(u32)) + return -EINVAL; + if (tb[TCA_POLICE_RESULT-1] != NULL && + RTA_PAYLOAD(tb[TCA_POLICE_RESULT-1]) != sizeof(u32)) + return -EINVAL; + + if (parm->index && (p = tcf_police_lookup(parm->index)) != NULL) { + a->priv = p; + if (bind) { + p->bindcnt += 1; + p->refcnt += 1; + } + if (ovr) + goto override; + return ret; + } + + p = kmalloc(sizeof(*p), GFP_KERNEL); + if (p == NULL) + return -ENOMEM; + memset(p, 0, sizeof(*p)); + + ret = ACT_P_CREATED; + p->refcnt = 1; + spin_lock_init(&p->lock); + p->stats_lock = &p->lock; + if (bind) + p->bindcnt = 1; +override: + if (parm->rate.rate) { + err = -ENOMEM; + R_tab = qdisc_get_rtab(&parm->rate, tb[TCA_POLICE_RATE-1]); + if (R_tab == NULL) + goto failure; + if (parm->peakrate.rate) { + P_tab = qdisc_get_rtab(&parm->peakrate, + tb[TCA_POLICE_PEAKRATE-1]); + if (p->P_tab == NULL) { + qdisc_put_rtab(R_tab); + goto failure; + } + } + } + /* No failure allowed after this point */ + spin_lock_bh(&p->lock); + if (R_tab != NULL) { + qdisc_put_rtab(p->R_tab); + p->R_tab = R_tab; + } + if (P_tab != NULL) { + qdisc_put_rtab(p->P_tab); + p->P_tab = P_tab; + } + + if (tb[TCA_POLICE_RESULT-1]) + p->result = *(u32*)RTA_DATA(tb[TCA_POLICE_RESULT-1]); + p->toks = p->burst = parm->burst; + p->mtu = parm->mtu; + if (p->mtu == 0) { + p->mtu = ~0; + if (p->R_tab) + p->mtu = 255<R_tab->rate.cell_log; + } + if (p->P_tab) + p->ptoks = L2T_P(p, p->mtu); + p->action = parm->action; + +#ifdef CONFIG_NET_ESTIMATOR + if (tb[TCA_POLICE_AVRATE-1]) + p->ewma_rate = *(u32*)RTA_DATA(tb[TCA_POLICE_AVRATE-1]); + if (est) + gen_replace_estimator(&p->bstats, &p->rate_est, p->stats_lock, est); +#endif + + spin_unlock_bh(&p->lock); + if (ret != ACT_P_CREATED) + return ret; + + PSCHED_GET_TIME(p->t_c); + p->index = parm->index ? : tcf_police_new_index(); + h = tcf_police_hash(p->index); + write_lock_bh(&police_lock); + p->next = tcf_police_ht[h]; + tcf_police_ht[h] = p; + write_unlock_bh(&police_lock); + + a->priv = p; + return ret; + +failure: + if (ret == ACT_P_CREATED) + kfree(p); + return err; +} + +static int tcf_act_police_cleanup(struct tc_action *a, int bind) +{ + struct tcf_police *p = PRIV(a); + + if (p != NULL) + return tcf_police_release(p, bind); + return 0; +} + +static int tcf_act_police(struct sk_buff *skb, struct tc_action *a, + struct tcf_result *res) +{ + psched_time_t now; + struct tcf_police *p = PRIV(a); + long toks; + long ptoks = 0; + + spin_lock(&p->lock); + + p->bstats.bytes += skb->len; + p->bstats.packets++; + +#ifdef CONFIG_NET_ESTIMATOR + if (p->ewma_rate && p->rate_est.bps >= p->ewma_rate) { + p->qstats.overlimits++; + spin_unlock(&p->lock); + return p->action; + } +#endif + + if (skb->len <= p->mtu) { + if (p->R_tab == NULL) { + spin_unlock(&p->lock); + return p->result; + } + + PSCHED_GET_TIME(now); + + toks = PSCHED_TDIFF_SAFE(now, p->t_c, p->burst); + + if (p->P_tab) { + ptoks = toks + p->ptoks; + if (ptoks > (long)L2T_P(p, p->mtu)) + ptoks = (long)L2T_P(p, p->mtu); + ptoks -= L2T_P(p, skb->len); + } + toks += p->toks; + if (toks > (long)p->burst) + toks = p->burst; + toks -= L2T(p, skb->len); + + if ((toks|ptoks) >= 0) { + p->t_c = now; + p->toks = toks; + p->ptoks = ptoks; + spin_unlock(&p->lock); + return p->result; + } + } + + p->qstats.overlimits++; + spin_unlock(&p->lock); + return p->action; +} + +static int +tcf_act_police_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref) +{ + unsigned char *b = skb->tail; + struct tc_police opt; + struct tcf_police *p = PRIV(a); + + opt.index = p->index; + opt.action = p->action; + opt.mtu = p->mtu; + opt.burst = p->burst; + opt.refcnt = p->refcnt - ref; + opt.bindcnt = p->bindcnt - bind; + if (p->R_tab) + opt.rate = p->R_tab->rate; + else + memset(&opt.rate, 0, sizeof(opt.rate)); + if (p->P_tab) + opt.peakrate = p->P_tab->rate; + else + memset(&opt.peakrate, 0, sizeof(opt.peakrate)); + RTA_PUT(skb, TCA_POLICE_TBF, sizeof(opt), &opt); + if (p->result) + RTA_PUT(skb, TCA_POLICE_RESULT, sizeof(int), &p->result); +#ifdef CONFIG_NET_ESTIMATOR + if (p->ewma_rate) + RTA_PUT(skb, TCA_POLICE_AVRATE, 4, &p->ewma_rate); +#endif + return skb->len; + +rtattr_failure: + skb_trim(skb, b - skb->data); + return -1; +} + +MODULE_AUTHOR("Alexey Kuznetsov"); +MODULE_DESCRIPTION("Policing actions"); +MODULE_LICENSE("GPL"); + +static struct tc_action_ops act_police_ops = { + .kind = "police", + .type = TCA_ID_POLICE, + .capab = TCA_CAP_NONE, + .owner = THIS_MODULE, + .act = tcf_act_police, + .dump = tcf_act_police_dump, + .cleanup = tcf_act_police_cleanup, + .lookup = tcf_hash_search, + .init = tcf_act_police_locate, + .walk = tcf_generic_walker +}; + +static int __init +police_init_module(void) +{ + return tcf_register_action(&act_police_ops); +} + +static void __exit +police_cleanup_module(void) +{ + tcf_unregister_action(&act_police_ops); +} + +module_init(police_init_module); +module_exit(police_cleanup_module); + +#else /* CONFIG_NET_CLS_ACT */ + +struct tcf_police * tcf_police_locate(struct rtattr *rta, struct rtattr *est) +{ + unsigned h; + struct tcf_police *p; + struct rtattr *tb[TCA_POLICE_MAX]; + struct tc_police *parm; + + if (rtattr_parse_nested(tb, TCA_POLICE_MAX, rta) < 0) + return NULL; + + if (tb[TCA_POLICE_TBF-1] == NULL || + RTA_PAYLOAD(tb[TCA_POLICE_TBF-1]) != sizeof(*parm)) + return NULL; + + parm = RTA_DATA(tb[TCA_POLICE_TBF-1]); + + if (parm->index && (p = tcf_police_lookup(parm->index)) != NULL) { + p->refcnt++; + return p; + } + + p = kmalloc(sizeof(*p), GFP_KERNEL); + if (p == NULL) + return NULL; + + memset(p, 0, sizeof(*p)); + p->refcnt = 1; + spin_lock_init(&p->lock); + p->stats_lock = &p->lock; + if (parm->rate.rate) { + p->R_tab = qdisc_get_rtab(&parm->rate, tb[TCA_POLICE_RATE-1]); + if (p->R_tab == NULL) + goto failure; + if (parm->peakrate.rate) { + p->P_tab = qdisc_get_rtab(&parm->peakrate, + tb[TCA_POLICE_PEAKRATE-1]); + if (p->P_tab == NULL) + goto failure; + } + } + if (tb[TCA_POLICE_RESULT-1]) { + if (RTA_PAYLOAD(tb[TCA_POLICE_RESULT-1]) != sizeof(u32)) + goto failure; + p->result = *(u32*)RTA_DATA(tb[TCA_POLICE_RESULT-1]); + } +#ifdef CONFIG_NET_ESTIMATOR + if (tb[TCA_POLICE_AVRATE-1]) { + if (RTA_PAYLOAD(tb[TCA_POLICE_AVRATE-1]) != sizeof(u32)) + goto failure; + p->ewma_rate = *(u32*)RTA_DATA(tb[TCA_POLICE_AVRATE-1]); + } +#endif + p->toks = p->burst = parm->burst; + p->mtu = parm->mtu; + if (p->mtu == 0) { + p->mtu = ~0; + if (p->R_tab) + p->mtu = 255<R_tab->rate.cell_log; + } + if (p->P_tab) + p->ptoks = L2T_P(p, p->mtu); + PSCHED_GET_TIME(p->t_c); + p->index = parm->index ? : tcf_police_new_index(); + p->action = parm->action; +#ifdef CONFIG_NET_ESTIMATOR + if (est) + gen_new_estimator(&p->bstats, &p->rate_est, p->stats_lock, est); +#endif + h = tcf_police_hash(p->index); + write_lock_bh(&police_lock); + p->next = tcf_police_ht[h]; + tcf_police_ht[h] = p; + write_unlock_bh(&police_lock); + return p; + +failure: + if (p->R_tab) + qdisc_put_rtab(p->R_tab); + kfree(p); + return NULL; +} + +int tcf_police(struct sk_buff *skb, struct tcf_police *p) +{ + psched_time_t now; + long toks; + long ptoks = 0; + + spin_lock(&p->lock); + + p->bstats.bytes += skb->len; + p->bstats.packets++; + +#ifdef CONFIG_NET_ESTIMATOR + if (p->ewma_rate && p->rate_est.bps >= p->ewma_rate) { + p->qstats.overlimits++; + spin_unlock(&p->lock); + return p->action; + } +#endif + + if (skb->len <= p->mtu) { + if (p->R_tab == NULL) { + spin_unlock(&p->lock); + return p->result; + } + + PSCHED_GET_TIME(now); + + toks = PSCHED_TDIFF_SAFE(now, p->t_c, p->burst); + + if (p->P_tab) { + ptoks = toks + p->ptoks; + if (ptoks > (long)L2T_P(p, p->mtu)) + ptoks = (long)L2T_P(p, p->mtu); + ptoks -= L2T_P(p, skb->len); + } + toks += p->toks; + if (toks > (long)p->burst) + toks = p->burst; + toks -= L2T(p, skb->len); + + if ((toks|ptoks) >= 0) { + p->t_c = now; + p->toks = toks; + p->ptoks = ptoks; + spin_unlock(&p->lock); + return p->result; + } + } + + p->qstats.overlimits++; + spin_unlock(&p->lock); + return p->action; +} +EXPORT_SYMBOL(tcf_police); + +int tcf_police_dump(struct sk_buff *skb, struct tcf_police *p) +{ + unsigned char *b = skb->tail; + struct tc_police opt; + + opt.index = p->index; + opt.action = p->action; + opt.mtu = p->mtu; + opt.burst = p->burst; + if (p->R_tab) + opt.rate = p->R_tab->rate; + else + memset(&opt.rate, 0, sizeof(opt.rate)); + if (p->P_tab) + opt.peakrate = p->P_tab->rate; + else + memset(&opt.peakrate, 0, sizeof(opt.peakrate)); + RTA_PUT(skb, TCA_POLICE_TBF, sizeof(opt), &opt); + if (p->result) + RTA_PUT(skb, TCA_POLICE_RESULT, sizeof(int), &p->result); +#ifdef CONFIG_NET_ESTIMATOR + if (p->ewma_rate) + RTA_PUT(skb, TCA_POLICE_AVRATE, 4, &p->ewma_rate); +#endif + return skb->len; + +rtattr_failure: + skb_trim(skb, b - skb->data); + return -1; +} + +int tcf_police_dump_stats(struct sk_buff *skb, struct tcf_police *p) +{ + struct gnet_dump d; + + if (gnet_stats_start_copy_compat(skb, TCA_STATS2, TCA_STATS, + TCA_XSTATS, p->stats_lock, &d) < 0) + goto errout; + + if (gnet_stats_copy_basic(&d, &p->bstats) < 0 || +#ifdef CONFIG_NET_ESTIMATOR + gnet_stats_copy_rate_est(&d, &p->rate_est) < 0 || +#endif + gnet_stats_copy_queue(&d, &p->qstats) < 0) + goto errout; + + if (gnet_stats_finish_copy(&d) < 0) + goto errout; + + return 0; + +errout: + return -1; +} + +#endif /* CONFIG_NET_CLS_ACT */ diff --git a/net/sched/act_simple.c b/net/sched/act_simple.c new file mode 100644 index 0000000..e5f2e1f --- /dev/null +++ b/net/sched/act_simple.c @@ -0,0 +1,92 @@ +/* + * net/sched/simp.c Simple example of an action + * + * 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 (at your option) any later version. + * + * Authors: Jamal Hadi Salim (2005) + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define TCA_ACT_SIMP 22 + +/* XXX: Hide all these common elements under some macro + * probably +*/ +#include +#include + +/* use generic hash table with 8 buckets */ +#define MY_TAB_SIZE 8 +#define MY_TAB_MASK (MY_TAB_SIZE - 1) +static u32 idx_gen; +static struct tcf_defact *tcf_simp_ht[MY_TAB_SIZE]; +static DEFINE_RWLOCK(simp_lock); + +/* override the defaults */ +#define tcf_st tcf_defact +#define tc_st tc_defact +#define tcf_t_lock simp_lock +#define tcf_ht tcf_simp_ht + +#define CONFIG_NET_ACT_INIT 1 +#include +#include + +static int tcf_simp(struct sk_buff *skb, struct tc_action *a, struct tcf_result *res) +{ + struct tcf_defact *p = PRIV(a, defact); + + spin_lock(&p->lock); + p->tm.lastuse = jiffies; + p->bstats.bytes += skb->len; + p->bstats.packets++; + + /* print policy string followed by _ then packet count + * Example if this was the 3rd packet and the string was "hello" + * then it would look like "hello_3" (without quotes) + **/ + printk("simple: %s_%d\n", (char *)p->defdata, p->bstats.packets); + spin_unlock(&p->lock); + return p->action; +} + +static struct tc_action_ops act_simp_ops = { + .kind = "simple", + .type = TCA_ACT_SIMP, + .capab = TCA_CAP_NONE, + .owner = THIS_MODULE, + .act = tcf_simp, + tca_use_default_ops +}; + +MODULE_AUTHOR("Jamal Hadi Salim(2005)"); +MODULE_DESCRIPTION("Simple example action"); +MODULE_LICENSE("GPL"); + +static int __init simp_init_module(void) +{ + int ret = tcf_register_action(&act_simp_ops); + if (!ret) + printk("Simple TC action Loaded\n"); + return ret; +} + +static void __exit simp_cleanup_module(void) +{ + tcf_unregister_action(&act_simp_ops); +} + +module_init(simp_init_module); +module_exit(simp_cleanup_module); diff --git a/net/sched/gact.c b/net/sched/gact.c deleted file mode 100644 index a1e68f7..0000000 --- a/net/sched/gact.c +++ /dev/null @@ -1,230 +0,0 @@ -/* - * net/sched/gact.c Generic actions - * - * 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 (at your option) any later version. - * - * copyright Jamal Hadi Salim (2002-4) - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* use generic hash table */ -#define MY_TAB_SIZE 16 -#define MY_TAB_MASK 15 - -static u32 idx_gen; -static struct tcf_gact *tcf_gact_ht[MY_TAB_SIZE]; -static DEFINE_RWLOCK(gact_lock); - -/* ovewrride the defaults */ -#define tcf_st tcf_gact -#define tc_st tc_gact -#define tcf_t_lock gact_lock -#define tcf_ht tcf_gact_ht - -#define CONFIG_NET_ACT_INIT 1 -#include - -#ifdef CONFIG_GACT_PROB -static int gact_net_rand(struct tcf_gact *p) -{ - if (net_random()%p->pval) - return p->action; - return p->paction; -} - -static int gact_determ(struct tcf_gact *p) -{ - if (p->bstats.packets%p->pval) - return p->action; - return p->paction; -} - -typedef int (*g_rand)(struct tcf_gact *p); -static g_rand gact_rand[MAX_RAND]= { NULL, gact_net_rand, gact_determ }; -#endif - -static int tcf_gact_init(struct rtattr *rta, struct rtattr *est, - struct tc_action *a, int ovr, int bind) -{ - struct rtattr *tb[TCA_GACT_MAX]; - struct tc_gact *parm; - struct tcf_gact *p; - int ret = 0; - - if (rta == NULL || rtattr_parse_nested(tb, TCA_GACT_MAX, rta) < 0) - return -EINVAL; - - if (tb[TCA_GACT_PARMS - 1] == NULL || - RTA_PAYLOAD(tb[TCA_GACT_PARMS - 1]) < sizeof(*parm)) - return -EINVAL; - parm = RTA_DATA(tb[TCA_GACT_PARMS - 1]); - - if (tb[TCA_GACT_PROB-1] != NULL) -#ifdef CONFIG_GACT_PROB - if (RTA_PAYLOAD(tb[TCA_GACT_PROB-1]) < sizeof(struct tc_gact_p)) - return -EINVAL; -#else - return -EOPNOTSUPP; -#endif - - p = tcf_hash_check(parm->index, a, ovr, bind); - if (p == NULL) { - p = tcf_hash_create(parm->index, est, a, sizeof(*p), ovr, bind); - if (p == NULL) - return -ENOMEM; - ret = ACT_P_CREATED; - } else { - if (!ovr) { - tcf_hash_release(p, bind); - return -EEXIST; - } - } - - spin_lock_bh(&p->lock); - p->action = parm->action; -#ifdef CONFIG_GACT_PROB - if (tb[TCA_GACT_PROB-1] != NULL) { - struct tc_gact_p *p_parm = RTA_DATA(tb[TCA_GACT_PROB-1]); - p->paction = p_parm->paction; - p->pval = p_parm->pval; - p->ptype = p_parm->ptype; - } -#endif - spin_unlock_bh(&p->lock); - if (ret == ACT_P_CREATED) - tcf_hash_insert(p); - return ret; -} - -static int -tcf_gact_cleanup(struct tc_action *a, int bind) -{ - struct tcf_gact *p = PRIV(a, gact); - - if (p != NULL) - return tcf_hash_release(p, bind); - return 0; -} - -static int -tcf_gact(struct sk_buff *skb, struct tc_action *a, struct tcf_result *res) -{ - struct tcf_gact *p = PRIV(a, gact); - int action = TC_ACT_SHOT; - - spin_lock(&p->lock); -#ifdef CONFIG_GACT_PROB - if (p->ptype && gact_rand[p->ptype] != NULL) - action = gact_rand[p->ptype](p); - else - action = p->action; -#else - action = p->action; -#endif - p->bstats.bytes += skb->len; - p->bstats.packets++; - if (action == TC_ACT_SHOT) - p->qstats.drops++; - p->tm.lastuse = jiffies; - spin_unlock(&p->lock); - - return action; -} - -static int -tcf_gact_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref) -{ - unsigned char *b = skb->tail; - struct tc_gact opt; - struct tcf_gact *p = PRIV(a, gact); - struct tcf_t t; - - opt.index = p->index; - opt.refcnt = p->refcnt - ref; - opt.bindcnt = p->bindcnt - bind; - opt.action = p->action; - RTA_PUT(skb, TCA_GACT_PARMS, sizeof(opt), &opt); -#ifdef CONFIG_GACT_PROB - if (p->ptype) { - struct tc_gact_p p_opt; - p_opt.paction = p->paction; - p_opt.pval = p->pval; - p_opt.ptype = p->ptype; - RTA_PUT(skb, TCA_GACT_PROB, sizeof(p_opt), &p_opt); - } -#endif - t.install = jiffies_to_clock_t(jiffies - p->tm.install); - t.lastuse = jiffies_to_clock_t(jiffies - p->tm.lastuse); - t.expires = jiffies_to_clock_t(p->tm.expires); - RTA_PUT(skb, TCA_GACT_TM, sizeof(t), &t); - return skb->len; - - rtattr_failure: - skb_trim(skb, b - skb->data); - return -1; -} - -static struct tc_action_ops act_gact_ops = { - .kind = "gact", - .type = TCA_ACT_GACT, - .capab = TCA_CAP_NONE, - .owner = THIS_MODULE, - .act = tcf_gact, - .dump = tcf_gact_dump, - .cleanup = tcf_gact_cleanup, - .lookup = tcf_hash_search, - .init = tcf_gact_init, - .walk = tcf_generic_walker -}; - -MODULE_AUTHOR("Jamal Hadi Salim(2002-4)"); -MODULE_DESCRIPTION("Generic Classifier actions"); -MODULE_LICENSE("GPL"); - -static int __init -gact_init_module(void) -{ -#ifdef CONFIG_GACT_PROB - printk("GACT probability on\n"); -#else - printk("GACT probability NOT on\n"); -#endif - return tcf_register_action(&act_gact_ops); -} - -static void __exit -gact_cleanup_module(void) -{ - tcf_unregister_action(&act_gact_ops); -} - -module_init(gact_init_module); -module_exit(gact_cleanup_module); diff --git a/net/sched/ipt.c b/net/sched/ipt.c deleted file mode 100644 index b500193..0000000 --- a/net/sched/ipt.c +++ /dev/null @@ -1,328 +0,0 @@ -/* - * net/sched/ipt.c iptables target interface - * - *TODO: Add other tables. For now we only support the ipv4 table targets - * - * 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 (at your option) any later version. - * - * Copyright: Jamal Hadi Salim (2002-4) - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -/* use generic hash table */ -#define MY_TAB_SIZE 16 -#define MY_TAB_MASK 15 - -static u32 idx_gen; -static struct tcf_ipt *tcf_ipt_ht[MY_TAB_SIZE]; -/* ipt hash table lock */ -static DEFINE_RWLOCK(ipt_lock); - -/* ovewrride the defaults */ -#define tcf_st tcf_ipt -#define tcf_t_lock ipt_lock -#define tcf_ht tcf_ipt_ht - -#define CONFIG_NET_ACT_INIT -#include - -static int -ipt_init_target(struct ipt_entry_target *t, char *table, unsigned int hook) -{ - struct ipt_target *target; - int ret = 0; - - target = ipt_find_target(t->u.user.name, t->u.user.revision); - if (!target) - return -ENOENT; - - DPRINTK("ipt_init_target: found %s\n", target->name); - t->u.kernel.target = target; - - if (t->u.kernel.target->checkentry - && !t->u.kernel.target->checkentry(table, NULL, t->data, - t->u.target_size - sizeof(*t), - hook)) { - DPRINTK("ipt_init_target: check failed for `%s'.\n", - t->u.kernel.target->name); - module_put(t->u.kernel.target->me); - ret = -EINVAL; - } - - return ret; -} - -static void -ipt_destroy_target(struct ipt_entry_target *t) -{ - if (t->u.kernel.target->destroy) - t->u.kernel.target->destroy(t->data, - t->u.target_size - sizeof(*t)); - module_put(t->u.kernel.target->me); -} - -static int -tcf_ipt_release(struct tcf_ipt *p, int bind) -{ - int ret = 0; - if (p) { - if (bind) - p->bindcnt--; - p->refcnt--; - if (p->bindcnt <= 0 && p->refcnt <= 0) { - ipt_destroy_target(p->t); - kfree(p->tname); - kfree(p->t); - tcf_hash_destroy(p); - ret = ACT_P_DELETED; - } - } - return ret; -} - -static int -tcf_ipt_init(struct rtattr *rta, struct rtattr *est, struct tc_action *a, - int ovr, int bind) -{ - struct rtattr *tb[TCA_IPT_MAX]; - struct tcf_ipt *p; - struct ipt_entry_target *td, *t; - char *tname; - int ret = 0, err; - u32 hook = 0; - u32 index = 0; - - if (rta == NULL || rtattr_parse_nested(tb, TCA_IPT_MAX, rta) < 0) - return -EINVAL; - - if (tb[TCA_IPT_HOOK-1] == NULL || - RTA_PAYLOAD(tb[TCA_IPT_HOOK-1]) < sizeof(u32)) - return -EINVAL; - if (tb[TCA_IPT_TARG-1] == NULL || - RTA_PAYLOAD(tb[TCA_IPT_TARG-1]) < sizeof(*t)) - return -EINVAL; - td = (struct ipt_entry_target *)RTA_DATA(tb[TCA_IPT_TARG-1]); - if (RTA_PAYLOAD(tb[TCA_IPT_TARG-1]) < td->u.target_size) - return -EINVAL; - - if (tb[TCA_IPT_INDEX-1] != NULL && - RTA_PAYLOAD(tb[TCA_IPT_INDEX-1]) >= sizeof(u32)) - index = *(u32 *)RTA_DATA(tb[TCA_IPT_INDEX-1]); - - p = tcf_hash_check(index, a, ovr, bind); - if (p == NULL) { - p = tcf_hash_create(index, est, a, sizeof(*p), ovr, bind); - if (p == NULL) - return -ENOMEM; - ret = ACT_P_CREATED; - } else { - if (!ovr) { - tcf_ipt_release(p, bind); - return -EEXIST; - } - } - - hook = *(u32 *)RTA_DATA(tb[TCA_IPT_HOOK-1]); - - err = -ENOMEM; - tname = kmalloc(IFNAMSIZ, GFP_KERNEL); - if (tname == NULL) - goto err1; - if (tb[TCA_IPT_TABLE - 1] == NULL || - rtattr_strlcpy(tname, tb[TCA_IPT_TABLE-1], IFNAMSIZ) >= IFNAMSIZ) - strcpy(tname, "mangle"); - - t = kmalloc(td->u.target_size, GFP_KERNEL); - if (t == NULL) - goto err2; - memcpy(t, td, td->u.target_size); - - if ((err = ipt_init_target(t, tname, hook)) < 0) - goto err3; - - spin_lock_bh(&p->lock); - if (ret != ACT_P_CREATED) { - ipt_destroy_target(p->t); - kfree(p->tname); - kfree(p->t); - } - p->tname = tname; - p->t = t; - p->hook = hook; - spin_unlock_bh(&p->lock); - if (ret == ACT_P_CREATED) - tcf_hash_insert(p); - return ret; - -err3: - kfree(t); -err2: - kfree(tname); -err1: - kfree(p); - return err; -} - -static int -tcf_ipt_cleanup(struct tc_action *a, int bind) -{ - struct tcf_ipt *p = PRIV(a, ipt); - return tcf_ipt_release(p, bind); -} - -static int -tcf_ipt(struct sk_buff *skb, struct tc_action *a, struct tcf_result *res) -{ - int ret = 0, result = 0; - struct tcf_ipt *p = PRIV(a, ipt); - - if (skb_cloned(skb)) { - if (pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) - return TC_ACT_UNSPEC; - } - - spin_lock(&p->lock); - - p->tm.lastuse = jiffies; - p->bstats.bytes += skb->len; - p->bstats.packets++; - - /* yes, we have to worry about both in and out dev - worry later - danger - this API seems to have changed - from earlier kernels */ - - /* iptables targets take a double skb pointer in case the skb - * needs to be replaced. We don't own the skb, so this must not - * happen. The pskb_expand_head above should make sure of this */ - ret = p->t->u.kernel.target->target(&skb, skb->dev, NULL, - p->hook, p->t->data, NULL); - switch (ret) { - case NF_ACCEPT: - result = TC_ACT_OK; - break; - case NF_DROP: - result = TC_ACT_SHOT; - p->qstats.drops++; - break; - case IPT_CONTINUE: - result = TC_ACT_PIPE; - break; - default: - if (net_ratelimit()) - printk("Bogus netfilter code %d assume ACCEPT\n", ret); - result = TC_POLICE_OK; - break; - } - spin_unlock(&p->lock); - return result; - -} - -static int -tcf_ipt_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref) -{ - struct ipt_entry_target *t; - struct tcf_t tm; - struct tc_cnt c; - unsigned char *b = skb->tail; - struct tcf_ipt *p = PRIV(a, ipt); - - /* for simple targets kernel size == user size - ** user name = target name - ** for foolproof you need to not assume this - */ - - t = kmalloc(p->t->u.user.target_size, GFP_ATOMIC); - if (t == NULL) - goto rtattr_failure; - - c.bindcnt = p->bindcnt - bind; - c.refcnt = p->refcnt - ref; - memcpy(t, p->t, p->t->u.user.target_size); - strcpy(t->u.user.name, p->t->u.kernel.target->name); - - DPRINTK("\ttcf_ipt_dump tablename %s length %d\n", p->tname, - strlen(p->tname)); - DPRINTK("\tdump target name %s size %d size user %d " - "data[0] %x data[1] %x\n", p->t->u.kernel.target->name, - p->t->u.target_size, p->t->u.user.target_size, - p->t->data[0], p->t->data[1]); - RTA_PUT(skb, TCA_IPT_TARG, p->t->u.user.target_size, t); - RTA_PUT(skb, TCA_IPT_INDEX, 4, &p->index); - RTA_PUT(skb, TCA_IPT_HOOK, 4, &p->hook); - RTA_PUT(skb, TCA_IPT_CNT, sizeof(struct tc_cnt), &c); - RTA_PUT(skb, TCA_IPT_TABLE, IFNAMSIZ, p->tname); - tm.install = jiffies_to_clock_t(jiffies - p->tm.install); - tm.lastuse = jiffies_to_clock_t(jiffies - p->tm.lastuse); - tm.expires = jiffies_to_clock_t(p->tm.expires); - RTA_PUT(skb, TCA_IPT_TM, sizeof (tm), &tm); - kfree(t); - return skb->len; - - rtattr_failure: - skb_trim(skb, b - skb->data); - kfree(t); - return -1; -} - -static struct tc_action_ops act_ipt_ops = { - .kind = "ipt", - .type = TCA_ACT_IPT, - .capab = TCA_CAP_NONE, - .owner = THIS_MODULE, - .act = tcf_ipt, - .dump = tcf_ipt_dump, - .cleanup = tcf_ipt_cleanup, - .lookup = tcf_hash_search, - .init = tcf_ipt_init, - .walk = tcf_generic_walker -}; - -MODULE_AUTHOR("Jamal Hadi Salim(2002-4)"); -MODULE_DESCRIPTION("Iptables target actions"); -MODULE_LICENSE("GPL"); - -static int __init -ipt_init_module(void) -{ - return tcf_register_action(&act_ipt_ops); -} - -static void __exit -ipt_cleanup_module(void) -{ - tcf_unregister_action(&act_ipt_ops); -} - -module_init(ipt_init_module); -module_exit(ipt_cleanup_module); diff --git a/net/sched/mirred.c b/net/sched/mirred.c deleted file mode 100644 index 4fcccbd..0000000 --- a/net/sched/mirred.c +++ /dev/null @@ -1,275 +0,0 @@ -/* - * net/sched/mirred.c packet mirroring and redirect actions - * - * 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 (at your option) any later version. - * - * Authors: Jamal Hadi Salim (2002-4) - * - * TODO: Add ingress support (and socket redirect support) - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - - -/* use generic hash table */ -#define MY_TAB_SIZE 8 -#define MY_TAB_MASK (MY_TAB_SIZE - 1) -static u32 idx_gen; -static struct tcf_mirred *tcf_mirred_ht[MY_TAB_SIZE]; -static DEFINE_RWLOCK(mirred_lock); - -/* ovewrride the defaults */ -#define tcf_st tcf_mirred -#define tc_st tc_mirred -#define tcf_t_lock mirred_lock -#define tcf_ht tcf_mirred_ht - -#define CONFIG_NET_ACT_INIT 1 -#include - -static inline int -tcf_mirred_release(struct tcf_mirred *p, int bind) -{ - if (p) { - if (bind) - p->bindcnt--; - p->refcnt--; - if(!p->bindcnt && p->refcnt <= 0) { - dev_put(p->dev); - tcf_hash_destroy(p); - return 1; - } - } - return 0; -} - -static int -tcf_mirred_init(struct rtattr *rta, struct rtattr *est, struct tc_action *a, - int ovr, int bind) -{ - struct rtattr *tb[TCA_MIRRED_MAX]; - struct tc_mirred *parm; - struct tcf_mirred *p; - struct net_device *dev = NULL; - int ret = 0; - int ok_push = 0; - - if (rta == NULL || rtattr_parse_nested(tb, TCA_MIRRED_MAX, rta) < 0) - return -EINVAL; - - if (tb[TCA_MIRRED_PARMS-1] == NULL || - RTA_PAYLOAD(tb[TCA_MIRRED_PARMS-1]) < sizeof(*parm)) - return -EINVAL; - parm = RTA_DATA(tb[TCA_MIRRED_PARMS-1]); - - if (parm->ifindex) { - dev = __dev_get_by_index(parm->ifindex); - if (dev == NULL) - return -ENODEV; - switch (dev->type) { - case ARPHRD_TUNNEL: - case ARPHRD_TUNNEL6: - case ARPHRD_SIT: - case ARPHRD_IPGRE: - case ARPHRD_VOID: - case ARPHRD_NONE: - ok_push = 0; - break; - default: - ok_push = 1; - break; - } - } - - p = tcf_hash_check(parm->index, a, ovr, bind); - if (p == NULL) { - if (!parm->ifindex) - return -EINVAL; - p = tcf_hash_create(parm->index, est, a, sizeof(*p), ovr, bind); - if (p == NULL) - return -ENOMEM; - ret = ACT_P_CREATED; - } else { - if (!ovr) { - tcf_mirred_release(p, bind); - return -EEXIST; - } - } - - spin_lock_bh(&p->lock); - p->action = parm->action; - p->eaction = parm->eaction; - if (parm->ifindex) { - p->ifindex = parm->ifindex; - if (ret != ACT_P_CREATED) - dev_put(p->dev); - p->dev = dev; - dev_hold(dev); - p->ok_push = ok_push; - } - spin_unlock_bh(&p->lock); - if (ret == ACT_P_CREATED) - tcf_hash_insert(p); - - DPRINTK("tcf_mirred_init index %d action %d eaction %d device %s " - "ifindex %d\n", parm->index, parm->action, parm->eaction, - dev->name, parm->ifindex); - return ret; -} - -static int -tcf_mirred_cleanup(struct tc_action *a, int bind) -{ - struct tcf_mirred *p = PRIV(a, mirred); - - if (p != NULL) - return tcf_mirred_release(p, bind); - return 0; -} - -static int -tcf_mirred(struct sk_buff *skb, struct tc_action *a, struct tcf_result *res) -{ - struct tcf_mirred *p = PRIV(a, mirred); - struct net_device *dev; - struct sk_buff *skb2 = NULL; - u32 at = G_TC_AT(skb->tc_verd); - - spin_lock(&p->lock); - - dev = p->dev; - p->tm.lastuse = jiffies; - - if (!(dev->flags&IFF_UP) ) { - if (net_ratelimit()) - printk("mirred to Houston: device %s is gone!\n", - dev->name); -bad_mirred: - if (skb2 != NULL) - kfree_skb(skb2); - p->qstats.overlimits++; - p->bstats.bytes += skb->len; - p->bstats.packets++; - spin_unlock(&p->lock); - /* should we be asking for packet to be dropped? - * may make sense for redirect case only - */ - return TC_ACT_SHOT; - } - - skb2 = skb_clone(skb, GFP_ATOMIC); - if (skb2 == NULL) - goto bad_mirred; - if (p->eaction != TCA_EGRESS_MIRROR && p->eaction != TCA_EGRESS_REDIR) { - if (net_ratelimit()) - printk("tcf_mirred unknown action %d\n", p->eaction); - goto bad_mirred; - } - - p->bstats.bytes += skb2->len; - p->bstats.packets++; - if (!(at & AT_EGRESS)) - if (p->ok_push) - skb_push(skb2, skb2->dev->hard_header_len); - - /* mirror is always swallowed */ - if (p->eaction != TCA_EGRESS_MIRROR) - skb2->tc_verd = SET_TC_FROM(skb2->tc_verd, at); - - skb2->dev = dev; - skb2->input_dev = skb->dev; - dev_queue_xmit(skb2); - spin_unlock(&p->lock); - return p->action; -} - -static int -tcf_mirred_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref) -{ - unsigned char *b = skb->tail; - struct tc_mirred opt; - struct tcf_mirred *p = PRIV(a, mirred); - struct tcf_t t; - - opt.index = p->index; - opt.action = p->action; - opt.refcnt = p->refcnt - ref; - opt.bindcnt = p->bindcnt - bind; - opt.eaction = p->eaction; - opt.ifindex = p->ifindex; - DPRINTK("tcf_mirred_dump index %d action %d eaction %d ifindex %d\n", - p->index, p->action, p->eaction, p->ifindex); - RTA_PUT(skb, TCA_MIRRED_PARMS, sizeof(opt), &opt); - t.install = jiffies_to_clock_t(jiffies - p->tm.install); - t.lastuse = jiffies_to_clock_t(jiffies - p->tm.lastuse); - t.expires = jiffies_to_clock_t(p->tm.expires); - RTA_PUT(skb, TCA_MIRRED_TM, sizeof(t), &t); - return skb->len; - - rtattr_failure: - skb_trim(skb, b - skb->data); - return -1; -} - -static struct tc_action_ops act_mirred_ops = { - .kind = "mirred", - .type = TCA_ACT_MIRRED, - .capab = TCA_CAP_NONE, - .owner = THIS_MODULE, - .act = tcf_mirred, - .dump = tcf_mirred_dump, - .cleanup = tcf_mirred_cleanup, - .lookup = tcf_hash_search, - .init = tcf_mirred_init, - .walk = tcf_generic_walker -}; - -MODULE_AUTHOR("Jamal Hadi Salim(2002)"); -MODULE_DESCRIPTION("Device Mirror/redirect actions"); -MODULE_LICENSE("GPL"); - -static int __init -mirred_init_module(void) -{ - printk("Mirror/redirect action on\n"); - return tcf_register_action(&act_mirred_ops); -} - -static void __exit -mirred_cleanup_module(void) -{ - tcf_unregister_action(&act_mirred_ops); -} - -module_init(mirred_init_module); -module_exit(mirred_cleanup_module); diff --git a/net/sched/pedit.c b/net/sched/pedit.c deleted file mode 100644 index 1742a68..0000000 --- a/net/sched/pedit.c +++ /dev/null @@ -1,289 +0,0 @@ -/* - * net/sched/pedit.c Generic packet editor - * - * 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 (at your option) any later version. - * - * Authors: Jamal Hadi Salim (2002-4) - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -#define PEDIT_DEB 1 - -/* use generic hash table */ -#define MY_TAB_SIZE 16 -#define MY_TAB_MASK 15 -static u32 idx_gen; -static struct tcf_pedit *tcf_pedit_ht[MY_TAB_SIZE]; -static DEFINE_RWLOCK(pedit_lock); - -#define tcf_st tcf_pedit -#define tc_st tc_pedit -#define tcf_t_lock pedit_lock -#define tcf_ht tcf_pedit_ht - -#define CONFIG_NET_ACT_INIT 1 -#include - -static int -tcf_pedit_init(struct rtattr *rta, struct rtattr *est, struct tc_action *a, - int ovr, int bind) -{ - struct rtattr *tb[TCA_PEDIT_MAX]; - struct tc_pedit *parm; - int ret = 0; - struct tcf_pedit *p; - struct tc_pedit_key *keys = NULL; - int ksize; - - if (rta == NULL || rtattr_parse_nested(tb, TCA_PEDIT_MAX, rta) < 0) - return -EINVAL; - - if (tb[TCA_PEDIT_PARMS - 1] == NULL || - RTA_PAYLOAD(tb[TCA_PEDIT_PARMS-1]) < sizeof(*parm)) - return -EINVAL; - parm = RTA_DATA(tb[TCA_PEDIT_PARMS-1]); - ksize = parm->nkeys * sizeof(struct tc_pedit_key); - if (RTA_PAYLOAD(tb[TCA_PEDIT_PARMS-1]) < sizeof(*parm) + ksize) - return -EINVAL; - - p = tcf_hash_check(parm->index, a, ovr, bind); - if (p == NULL) { - if (!parm->nkeys) - return -EINVAL; - p = tcf_hash_create(parm->index, est, a, sizeof(*p), ovr, bind); - if (p == NULL) - return -ENOMEM; - keys = kmalloc(ksize, GFP_KERNEL); - if (keys == NULL) { - kfree(p); - return -ENOMEM; - } - ret = ACT_P_CREATED; - } else { - if (!ovr) { - tcf_hash_release(p, bind); - return -EEXIST; - } - if (p->nkeys && p->nkeys != parm->nkeys) { - keys = kmalloc(ksize, GFP_KERNEL); - if (keys == NULL) - return -ENOMEM; - } - } - - spin_lock_bh(&p->lock); - p->flags = parm->flags; - p->action = parm->action; - if (keys) { - kfree(p->keys); - p->keys = keys; - p->nkeys = parm->nkeys; - } - memcpy(p->keys, parm->keys, ksize); - spin_unlock_bh(&p->lock); - if (ret == ACT_P_CREATED) - tcf_hash_insert(p); - return ret; -} - -static int -tcf_pedit_cleanup(struct tc_action *a, int bind) -{ - struct tcf_pedit *p = PRIV(a, pedit); - - if (p != NULL) { - struct tc_pedit_key *keys = p->keys; - if (tcf_hash_release(p, bind)) { - kfree(keys); - return 1; - } - } - return 0; -} - -static int -tcf_pedit(struct sk_buff *skb, struct tc_action *a, struct tcf_result *res) -{ - struct tcf_pedit *p = PRIV(a, pedit); - int i, munged = 0; - u8 *pptr; - - if (!(skb->tc_verd & TC_OK2MUNGE)) { - /* should we set skb->cloned? */ - if (pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) { - return p->action; - } - } - - pptr = skb->nh.raw; - - spin_lock(&p->lock); - - p->tm.lastuse = jiffies; - - if (p->nkeys > 0) { - struct tc_pedit_key *tkey = p->keys; - - for (i = p->nkeys; i > 0; i--, tkey++) { - u32 *ptr; - int offset = tkey->off; - - if (tkey->offmask) { - if (skb->len > tkey->at) { - char *j = pptr + tkey->at; - offset += ((*j & tkey->offmask) >> - tkey->shift); - } else { - goto bad; - } - } - - if (offset % 4) { - printk("offset must be on 32 bit boundaries\n"); - goto bad; - } - if (skb->len < 0 || (offset > 0 && offset > skb->len)) { - printk("offset %d cant exceed pkt length %d\n", - offset, skb->len); - goto bad; - } - - ptr = (u32 *)(pptr+offset); - /* just do it, baby */ - *ptr = ((*ptr & tkey->mask) ^ tkey->val); - munged++; - } - - if (munged) - skb->tc_verd = SET_TC_MUNGED(skb->tc_verd); - goto done; - } else { - printk("pedit BUG: index %d\n",p->index); - } - -bad: - p->qstats.overlimits++; -done: - p->bstats.bytes += skb->len; - p->bstats.packets++; - spin_unlock(&p->lock); - return p->action; -} - -static int -tcf_pedit_dump(struct sk_buff *skb, struct tc_action *a,int bind, int ref) -{ - unsigned char *b = skb->tail; - struct tc_pedit *opt; - struct tcf_pedit *p = PRIV(a, pedit); - struct tcf_t t; - int s; - - s = sizeof(*opt) + p->nkeys * sizeof(struct tc_pedit_key); - - /* netlink spinlocks held above us - must use ATOMIC */ - opt = kmalloc(s, GFP_ATOMIC); - if (opt == NULL) - return -ENOBUFS; - memset(opt, 0, s); - - memcpy(opt->keys, p->keys, p->nkeys * sizeof(struct tc_pedit_key)); - opt->index = p->index; - opt->nkeys = p->nkeys; - opt->flags = p->flags; - opt->action = p->action; - opt->refcnt = p->refcnt - ref; - opt->bindcnt = p->bindcnt - bind; - - -#ifdef PEDIT_DEB - { - /* Debug - get rid of later */ - int i; - struct tc_pedit_key *key = opt->keys; - - for (i=0; inkeys; i++, key++) { - printk( "\n key #%d",i); - printk( " at %d: val %08x mask %08x", - (unsigned int)key->off, - (unsigned int)key->val, - (unsigned int)key->mask); - } - } -#endif - - RTA_PUT(skb, TCA_PEDIT_PARMS, s, opt); - t.install = jiffies_to_clock_t(jiffies - p->tm.install); - t.lastuse = jiffies_to_clock_t(jiffies - p->tm.lastuse); - t.expires = jiffies_to_clock_t(p->tm.expires); - RTA_PUT(skb, TCA_PEDIT_TM, sizeof(t), &t); - kfree(opt); - return skb->len; - -rtattr_failure: - skb_trim(skb, b - skb->data); - kfree(opt); - return -1; -} - -static -struct tc_action_ops act_pedit_ops = { - .kind = "pedit", - .type = TCA_ACT_PEDIT, - .capab = TCA_CAP_NONE, - .owner = THIS_MODULE, - .act = tcf_pedit, - .dump = tcf_pedit_dump, - .cleanup = tcf_pedit_cleanup, - .lookup = tcf_hash_search, - .init = tcf_pedit_init, - .walk = tcf_generic_walker -}; - -MODULE_AUTHOR("Jamal Hadi Salim(2002-4)"); -MODULE_DESCRIPTION("Generic Packet Editor actions"); -MODULE_LICENSE("GPL"); - -static int __init -pedit_init_module(void) -{ - return tcf_register_action(&act_pedit_ops); -} - -static void __exit -pedit_cleanup_module(void) -{ - tcf_unregister_action(&act_pedit_ops); -} - -module_init(pedit_init_module); -module_exit(pedit_cleanup_module); - diff --git a/net/sched/police.c b/net/sched/police.c deleted file mode 100644 index fa877f8..0000000 --- a/net/sched/police.c +++ /dev/null @@ -1,604 +0,0 @@ -/* - * net/sched/police.c Input police filter. - * - * 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 (at your option) any later version. - * - * Authors: Alexey Kuznetsov, - * J Hadi Salim (action changes) - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define L2T(p,L) ((p)->R_tab->data[(L)>>(p)->R_tab->rate.cell_log]) -#define L2T_P(p,L) ((p)->P_tab->data[(L)>>(p)->P_tab->rate.cell_log]) -#define PRIV(a) ((struct tcf_police *) (a)->priv) - -/* use generic hash table */ -#define MY_TAB_SIZE 16 -#define MY_TAB_MASK 15 -static u32 idx_gen; -static struct tcf_police *tcf_police_ht[MY_TAB_SIZE]; -/* Policer hash table lock */ -static DEFINE_RWLOCK(police_lock); - -/* Each policer is serialized by its individual spinlock */ - -static __inline__ unsigned tcf_police_hash(u32 index) -{ - return index&0xF; -} - -static __inline__ struct tcf_police * tcf_police_lookup(u32 index) -{ - struct tcf_police *p; - - read_lock(&police_lock); - for (p = tcf_police_ht[tcf_police_hash(index)]; p; p = p->next) { - if (p->index == index) - break; - } - read_unlock(&police_lock); - return p; -} - -#ifdef CONFIG_NET_CLS_ACT -static int tcf_generic_walker(struct sk_buff *skb, struct netlink_callback *cb, - int type, struct tc_action *a) -{ - struct tcf_police *p; - int err = 0, index = -1, i = 0, s_i = 0, n_i = 0; - struct rtattr *r; - - read_lock(&police_lock); - - s_i = cb->args[0]; - - for (i = 0; i < MY_TAB_SIZE; i++) { - p = tcf_police_ht[tcf_police_hash(i)]; - - for (; p; p = p->next) { - index++; - if (index < s_i) - continue; - a->priv = p; - a->order = index; - r = (struct rtattr*) skb->tail; - RTA_PUT(skb, a->order, 0, NULL); - if (type == RTM_DELACTION) - err = tcf_action_dump_1(skb, a, 0, 1); - else - err = tcf_action_dump_1(skb, a, 0, 0); - if (err < 0) { - index--; - skb_trim(skb, (u8*)r - skb->data); - goto done; - } - r->rta_len = skb->tail - (u8*)r; - n_i++; - } - } -done: - read_unlock(&police_lock); - if (n_i) - cb->args[0] += n_i; - return n_i; - -rtattr_failure: - skb_trim(skb, (u8*)r - skb->data); - goto done; -} - -static inline int -tcf_hash_search(struct tc_action *a, u32 index) -{ - struct tcf_police *p = tcf_police_lookup(index); - - if (p != NULL) { - a->priv = p; - return 1; - } else { - return 0; - } -} -#endif - -static inline u32 tcf_police_new_index(void) -{ - do { - if (++idx_gen == 0) - idx_gen = 1; - } while (tcf_police_lookup(idx_gen)); - - return idx_gen; -} - -void tcf_police_destroy(struct tcf_police *p) -{ - unsigned h = tcf_police_hash(p->index); - struct tcf_police **p1p; - - for (p1p = &tcf_police_ht[h]; *p1p; p1p = &(*p1p)->next) { - if (*p1p == p) { - write_lock_bh(&police_lock); - *p1p = p->next; - write_unlock_bh(&police_lock); -#ifdef CONFIG_NET_ESTIMATOR - gen_kill_estimator(&p->bstats, &p->rate_est); -#endif - if (p->R_tab) - qdisc_put_rtab(p->R_tab); - if (p->P_tab) - qdisc_put_rtab(p->P_tab); - kfree(p); - return; - } - } - BUG_TRAP(0); -} - -#ifdef CONFIG_NET_CLS_ACT -static int tcf_act_police_locate(struct rtattr *rta, struct rtattr *est, - struct tc_action *a, int ovr, int bind) -{ - unsigned h; - int ret = 0, err; - struct rtattr *tb[TCA_POLICE_MAX]; - struct tc_police *parm; - struct tcf_police *p; - struct qdisc_rate_table *R_tab = NULL, *P_tab = NULL; - - if (rta == NULL || rtattr_parse_nested(tb, TCA_POLICE_MAX, rta) < 0) - return -EINVAL; - - if (tb[TCA_POLICE_TBF-1] == NULL || - RTA_PAYLOAD(tb[TCA_POLICE_TBF-1]) != sizeof(*parm)) - return -EINVAL; - parm = RTA_DATA(tb[TCA_POLICE_TBF-1]); - - if (tb[TCA_POLICE_RESULT-1] != NULL && - RTA_PAYLOAD(tb[TCA_POLICE_RESULT-1]) != sizeof(u32)) - return -EINVAL; - if (tb[TCA_POLICE_RESULT-1] != NULL && - RTA_PAYLOAD(tb[TCA_POLICE_RESULT-1]) != sizeof(u32)) - return -EINVAL; - - if (parm->index && (p = tcf_police_lookup(parm->index)) != NULL) { - a->priv = p; - if (bind) { - p->bindcnt += 1; - p->refcnt += 1; - } - if (ovr) - goto override; - return ret; - } - - p = kmalloc(sizeof(*p), GFP_KERNEL); - if (p == NULL) - return -ENOMEM; - memset(p, 0, sizeof(*p)); - - ret = ACT_P_CREATED; - p->refcnt = 1; - spin_lock_init(&p->lock); - p->stats_lock = &p->lock; - if (bind) - p->bindcnt = 1; -override: - if (parm->rate.rate) { - err = -ENOMEM; - R_tab = qdisc_get_rtab(&parm->rate, tb[TCA_POLICE_RATE-1]); - if (R_tab == NULL) - goto failure; - if (parm->peakrate.rate) { - P_tab = qdisc_get_rtab(&parm->peakrate, - tb[TCA_POLICE_PEAKRATE-1]); - if (p->P_tab == NULL) { - qdisc_put_rtab(R_tab); - goto failure; - } - } - } - /* No failure allowed after this point */ - spin_lock_bh(&p->lock); - if (R_tab != NULL) { - qdisc_put_rtab(p->R_tab); - p->R_tab = R_tab; - } - if (P_tab != NULL) { - qdisc_put_rtab(p->P_tab); - p->P_tab = P_tab; - } - - if (tb[TCA_POLICE_RESULT-1]) - p->result = *(u32*)RTA_DATA(tb[TCA_POLICE_RESULT-1]); - p->toks = p->burst = parm->burst; - p->mtu = parm->mtu; - if (p->mtu == 0) { - p->mtu = ~0; - if (p->R_tab) - p->mtu = 255<R_tab->rate.cell_log; - } - if (p->P_tab) - p->ptoks = L2T_P(p, p->mtu); - p->action = parm->action; - -#ifdef CONFIG_NET_ESTIMATOR - if (tb[TCA_POLICE_AVRATE-1]) - p->ewma_rate = *(u32*)RTA_DATA(tb[TCA_POLICE_AVRATE-1]); - if (est) - gen_replace_estimator(&p->bstats, &p->rate_est, p->stats_lock, est); -#endif - - spin_unlock_bh(&p->lock); - if (ret != ACT_P_CREATED) - return ret; - - PSCHED_GET_TIME(p->t_c); - p->index = parm->index ? : tcf_police_new_index(); - h = tcf_police_hash(p->index); - write_lock_bh(&police_lock); - p->next = tcf_police_ht[h]; - tcf_police_ht[h] = p; - write_unlock_bh(&police_lock); - - a->priv = p; - return ret; - -failure: - if (ret == ACT_P_CREATED) - kfree(p); - return err; -} - -static int tcf_act_police_cleanup(struct tc_action *a, int bind) -{ - struct tcf_police *p = PRIV(a); - - if (p != NULL) - return tcf_police_release(p, bind); - return 0; -} - -static int tcf_act_police(struct sk_buff *skb, struct tc_action *a, - struct tcf_result *res) -{ - psched_time_t now; - struct tcf_police *p = PRIV(a); - long toks; - long ptoks = 0; - - spin_lock(&p->lock); - - p->bstats.bytes += skb->len; - p->bstats.packets++; - -#ifdef CONFIG_NET_ESTIMATOR - if (p->ewma_rate && p->rate_est.bps >= p->ewma_rate) { - p->qstats.overlimits++; - spin_unlock(&p->lock); - return p->action; - } -#endif - - if (skb->len <= p->mtu) { - if (p->R_tab == NULL) { - spin_unlock(&p->lock); - return p->result; - } - - PSCHED_GET_TIME(now); - - toks = PSCHED_TDIFF_SAFE(now, p->t_c, p->burst); - - if (p->P_tab) { - ptoks = toks + p->ptoks; - if (ptoks > (long)L2T_P(p, p->mtu)) - ptoks = (long)L2T_P(p, p->mtu); - ptoks -= L2T_P(p, skb->len); - } - toks += p->toks; - if (toks > (long)p->burst) - toks = p->burst; - toks -= L2T(p, skb->len); - - if ((toks|ptoks) >= 0) { - p->t_c = now; - p->toks = toks; - p->ptoks = ptoks; - spin_unlock(&p->lock); - return p->result; - } - } - - p->qstats.overlimits++; - spin_unlock(&p->lock); - return p->action; -} - -static int -tcf_act_police_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref) -{ - unsigned char *b = skb->tail; - struct tc_police opt; - struct tcf_police *p = PRIV(a); - - opt.index = p->index; - opt.action = p->action; - opt.mtu = p->mtu; - opt.burst = p->burst; - opt.refcnt = p->refcnt - ref; - opt.bindcnt = p->bindcnt - bind; - if (p->R_tab) - opt.rate = p->R_tab->rate; - else - memset(&opt.rate, 0, sizeof(opt.rate)); - if (p->P_tab) - opt.peakrate = p->P_tab->rate; - else - memset(&opt.peakrate, 0, sizeof(opt.peakrate)); - RTA_PUT(skb, TCA_POLICE_TBF, sizeof(opt), &opt); - if (p->result) - RTA_PUT(skb, TCA_POLICE_RESULT, sizeof(int), &p->result); -#ifdef CONFIG_NET_ESTIMATOR - if (p->ewma_rate) - RTA_PUT(skb, TCA_POLICE_AVRATE, 4, &p->ewma_rate); -#endif - return skb->len; - -rtattr_failure: - skb_trim(skb, b - skb->data); - return -1; -} - -MODULE_AUTHOR("Alexey Kuznetsov"); -MODULE_DESCRIPTION("Policing actions"); -MODULE_LICENSE("GPL"); - -static struct tc_action_ops act_police_ops = { - .kind = "police", - .type = TCA_ID_POLICE, - .capab = TCA_CAP_NONE, - .owner = THIS_MODULE, - .act = tcf_act_police, - .dump = tcf_act_police_dump, - .cleanup = tcf_act_police_cleanup, - .lookup = tcf_hash_search, - .init = tcf_act_police_locate, - .walk = tcf_generic_walker -}; - -static int __init -police_init_module(void) -{ - return tcf_register_action(&act_police_ops); -} - -static void __exit -police_cleanup_module(void) -{ - tcf_unregister_action(&act_police_ops); -} - -module_init(police_init_module); -module_exit(police_cleanup_module); - -#else /* CONFIG_NET_CLS_ACT */ - -struct tcf_police * tcf_police_locate(struct rtattr *rta, struct rtattr *est) -{ - unsigned h; - struct tcf_police *p; - struct rtattr *tb[TCA_POLICE_MAX]; - struct tc_police *parm; - - if (rtattr_parse_nested(tb, TCA_POLICE_MAX, rta) < 0) - return NULL; - - if (tb[TCA_POLICE_TBF-1] == NULL || - RTA_PAYLOAD(tb[TCA_POLICE_TBF-1]) != sizeof(*parm)) - return NULL; - - parm = RTA_DATA(tb[TCA_POLICE_TBF-1]); - - if (parm->index && (p = tcf_police_lookup(parm->index)) != NULL) { - p->refcnt++; - return p; - } - - p = kmalloc(sizeof(*p), GFP_KERNEL); - if (p == NULL) - return NULL; - - memset(p, 0, sizeof(*p)); - p->refcnt = 1; - spin_lock_init(&p->lock); - p->stats_lock = &p->lock; - if (parm->rate.rate) { - p->R_tab = qdisc_get_rtab(&parm->rate, tb[TCA_POLICE_RATE-1]); - if (p->R_tab == NULL) - goto failure; - if (parm->peakrate.rate) { - p->P_tab = qdisc_get_rtab(&parm->peakrate, - tb[TCA_POLICE_PEAKRATE-1]); - if (p->P_tab == NULL) - goto failure; - } - } - if (tb[TCA_POLICE_RESULT-1]) { - if (RTA_PAYLOAD(tb[TCA_POLICE_RESULT-1]) != sizeof(u32)) - goto failure; - p->result = *(u32*)RTA_DATA(tb[TCA_POLICE_RESULT-1]); - } -#ifdef CONFIG_NET_ESTIMATOR - if (tb[TCA_POLICE_AVRATE-1]) { - if (RTA_PAYLOAD(tb[TCA_POLICE_AVRATE-1]) != sizeof(u32)) - goto failure; - p->ewma_rate = *(u32*)RTA_DATA(tb[TCA_POLICE_AVRATE-1]); - } -#endif - p->toks = p->burst = parm->burst; - p->mtu = parm->mtu; - if (p->mtu == 0) { - p->mtu = ~0; - if (p->R_tab) - p->mtu = 255<R_tab->rate.cell_log; - } - if (p->P_tab) - p->ptoks = L2T_P(p, p->mtu); - PSCHED_GET_TIME(p->t_c); - p->index = parm->index ? : tcf_police_new_index(); - p->action = parm->action; -#ifdef CONFIG_NET_ESTIMATOR - if (est) - gen_new_estimator(&p->bstats, &p->rate_est, p->stats_lock, est); -#endif - h = tcf_police_hash(p->index); - write_lock_bh(&police_lock); - p->next = tcf_police_ht[h]; - tcf_police_ht[h] = p; - write_unlock_bh(&police_lock); - return p; - -failure: - if (p->R_tab) - qdisc_put_rtab(p->R_tab); - kfree(p); - return NULL; -} - -int tcf_police(struct sk_buff *skb, struct tcf_police *p) -{ - psched_time_t now; - long toks; - long ptoks = 0; - - spin_lock(&p->lock); - - p->bstats.bytes += skb->len; - p->bstats.packets++; - -#ifdef CONFIG_NET_ESTIMATOR - if (p->ewma_rate && p->rate_est.bps >= p->ewma_rate) { - p->qstats.overlimits++; - spin_unlock(&p->lock); - return p->action; - } -#endif - - if (skb->len <= p->mtu) { - if (p->R_tab == NULL) { - spin_unlock(&p->lock); - return p->result; - } - - PSCHED_GET_TIME(now); - - toks = PSCHED_TDIFF_SAFE(now, p->t_c, p->burst); - - if (p->P_tab) { - ptoks = toks + p->ptoks; - if (ptoks > (long)L2T_P(p, p->mtu)) - ptoks = (long)L2T_P(p, p->mtu); - ptoks -= L2T_P(p, skb->len); - } - toks += p->toks; - if (toks > (long)p->burst) - toks = p->burst; - toks -= L2T(p, skb->len); - - if ((toks|ptoks) >= 0) { - p->t_c = now; - p->toks = toks; - p->ptoks = ptoks; - spin_unlock(&p->lock); - return p->result; - } - } - - p->qstats.overlimits++; - spin_unlock(&p->lock); - return p->action; -} -EXPORT_SYMBOL(tcf_police); - -int tcf_police_dump(struct sk_buff *skb, struct tcf_police *p) -{ - unsigned char *b = skb->tail; - struct tc_police opt; - - opt.index = p->index; - opt.action = p->action; - opt.mtu = p->mtu; - opt.burst = p->burst; - if (p->R_tab) - opt.rate = p->R_tab->rate; - else - memset(&opt.rate, 0, sizeof(opt.rate)); - if (p->P_tab) - opt.peakrate = p->P_tab->rate; - else - memset(&opt.peakrate, 0, sizeof(opt.peakrate)); - RTA_PUT(skb, TCA_POLICE_TBF, sizeof(opt), &opt); - if (p->result) - RTA_PUT(skb, TCA_POLICE_RESULT, sizeof(int), &p->result); -#ifdef CONFIG_NET_ESTIMATOR - if (p->ewma_rate) - RTA_PUT(skb, TCA_POLICE_AVRATE, 4, &p->ewma_rate); -#endif - return skb->len; - -rtattr_failure: - skb_trim(skb, b - skb->data); - return -1; -} - -int tcf_police_dump_stats(struct sk_buff *skb, struct tcf_police *p) -{ - struct gnet_dump d; - - if (gnet_stats_start_copy_compat(skb, TCA_STATS2, TCA_STATS, - TCA_XSTATS, p->stats_lock, &d) < 0) - goto errout; - - if (gnet_stats_copy_basic(&d, &p->bstats) < 0 || -#ifdef CONFIG_NET_ESTIMATOR - gnet_stats_copy_rate_est(&d, &p->rate_est) < 0 || -#endif - gnet_stats_copy_queue(&d, &p->qstats) < 0) - goto errout; - - if (gnet_stats_finish_copy(&d) < 0) - goto errout; - - return 0; - -errout: - return -1; -} - -#endif /* CONFIG_NET_CLS_ACT */ diff --git a/net/sched/simple.c b/net/sched/simple.c deleted file mode 100644 index e5f2e1f..0000000 --- a/net/sched/simple.c +++ /dev/null @@ -1,92 +0,0 @@ -/* - * net/sched/simp.c Simple example of an action - * - * 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 (at your option) any later version. - * - * Authors: Jamal Hadi Salim (2005) - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#define TCA_ACT_SIMP 22 - -/* XXX: Hide all these common elements under some macro - * probably -*/ -#include -#include - -/* use generic hash table with 8 buckets */ -#define MY_TAB_SIZE 8 -#define MY_TAB_MASK (MY_TAB_SIZE - 1) -static u32 idx_gen; -static struct tcf_defact *tcf_simp_ht[MY_TAB_SIZE]; -static DEFINE_RWLOCK(simp_lock); - -/* override the defaults */ -#define tcf_st tcf_defact -#define tc_st tc_defact -#define tcf_t_lock simp_lock -#define tcf_ht tcf_simp_ht - -#define CONFIG_NET_ACT_INIT 1 -#include -#include - -static int tcf_simp(struct sk_buff *skb, struct tc_action *a, struct tcf_result *res) -{ - struct tcf_defact *p = PRIV(a, defact); - - spin_lock(&p->lock); - p->tm.lastuse = jiffies; - p->bstats.bytes += skb->len; - p->bstats.packets++; - - /* print policy string followed by _ then packet count - * Example if this was the 3rd packet and the string was "hello" - * then it would look like "hello_3" (without quotes) - **/ - printk("simple: %s_%d\n", (char *)p->defdata, p->bstats.packets); - spin_unlock(&p->lock); - return p->action; -} - -static struct tc_action_ops act_simp_ops = { - .kind = "simple", - .type = TCA_ACT_SIMP, - .capab = TCA_CAP_NONE, - .owner = THIS_MODULE, - .act = tcf_simp, - tca_use_default_ops -}; - -MODULE_AUTHOR("Jamal Hadi Salim(2005)"); -MODULE_DESCRIPTION("Simple example action"); -MODULE_LICENSE("GPL"); - -static int __init simp_init_module(void) -{ - int ret = tcf_register_action(&act_simp_ops); - if (!ret) - printk("Simple TC action Loaded\n"); - return ret; -} - -static void __exit simp_cleanup_module(void) -{ - tcf_unregister_action(&act_simp_ops); -} - -module_init(simp_init_module); -module_exit(simp_cleanup_module); -- cgit v1.1 From 09a626600b437d91f6b13ade5c7c4b374893c54e Mon Sep 17 00:00:00 2001 From: Kris Katterjohn Date: Sun, 8 Jan 2006 22:24:28 -0800 Subject: [NET]: Change some "if (x) BUG();" to "BUG_ON(x);" This changes some simple "if (x) BUG();" statements to "BUG_ON(x);" Signed-off-by: Kris Katterjohn Signed-off-by: David S. Miller --- net/core/dev.c | 9 +++------ net/core/skbuff.c | 15 +++++---------- net/ipv4/icmp.c | 3 +-- net/ipv4/inetpeer.c | 6 ++---- net/ipv4/tcp_input.c | 2 +- net/key/af_key.c | 3 +-- net/sctp/sm_sideeffect.c | 3 +-- net/sunrpc/cache.c | 5 ++--- net/sunrpc/svc.c | 3 +-- net/xfrm/xfrm_algo.c | 6 ++---- net/xfrm/xfrm_policy.c | 6 ++---- 11 files changed, 21 insertions(+), 40 deletions(-) diff --git a/net/core/dev.c b/net/core/dev.c index 5081287..bf66b11 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1092,15 +1092,12 @@ int skb_checksum_help(struct sk_buff *skb, int inward) goto out; } - if (offset > (int)skb->len) - BUG(); + BUG_ON(offset > (int)skb->len); csum = skb_checksum(skb, offset, skb->len-offset, 0); offset = skb->tail - skb->h.raw; - if (offset <= 0) - BUG(); - if (skb->csum + 2 > offset) - BUG(); + BUG_ON(offset <= 0); + BUG_ON(skb->csum + 2 > offset); *(u16*)(skb->h.raw + skb->csum) = csum_fold(csum); skb->ip_summed = CHECKSUM_NONE; diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 070f91c..d0732e9 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -791,8 +791,7 @@ int ___pskb_trim(struct sk_buff *skb, unsigned int len, int realloc) int end = offset + skb_shinfo(skb)->frags[i].size; if (end > len) { if (skb_cloned(skb)) { - if (!realloc) - BUG(); + BUG_ON(!realloc); if (pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) return -ENOMEM; } @@ -894,8 +893,7 @@ unsigned char *__pskb_pull_tail(struct sk_buff *skb, int delta) struct sk_buff *insp = NULL; do { - if (!list) - BUG(); + BUG_ON(!list); if (list->len <= eat) { /* Eaten as whole. */ @@ -1199,8 +1197,7 @@ unsigned int skb_checksum(const struct sk_buff *skb, int offset, start = end; } } - if (len) - BUG(); + BUG_ON(len); return csum; } @@ -1282,8 +1279,7 @@ unsigned int skb_copy_and_csum_bits(const struct sk_buff *skb, int offset, start = end; } } - if (len) - BUG(); + BUG_ON(len); return csum; } @@ -1297,8 +1293,7 @@ void skb_copy_and_csum_dev(const struct sk_buff *skb, u8 *to) else csstart = skb_headlen(skb); - if (csstart > skb_headlen(skb)) - BUG(); + BUG_ON(csstart > skb_headlen(skb)); memcpy(to, skb->data, csstart); diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index be5a519..105039e 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c @@ -899,8 +899,7 @@ static void icmp_address_reply(struct sk_buff *skb) u32 _mask, *mp; mp = skb_header_pointer(skb, 0, sizeof(_mask), &_mask); - if (mp == NULL) - BUG(); + BUG_ON(mp == NULL); for (ifa = in_dev->ifa_list; ifa; ifa = ifa->ifa_next) { if (*mp == ifa->ifa_mask && inet_ifa_match(rt->rt_src, ifa)) diff --git a/net/ipv4/inetpeer.c b/net/ipv4/inetpeer.c index ce5fe3f..2160874 100644 --- a/net/ipv4/inetpeer.c +++ b/net/ipv4/inetpeer.c @@ -304,8 +304,7 @@ static void unlink_from_pool(struct inet_peer *p) /* look for a node to insert instead of p */ struct inet_peer *t; t = lookup_rightempty(p); - if (*stackptr[-1] != t) - BUG(); + BUG_ON(*stackptr[-1] != t); **--stackptr = t->avl_left; /* t is removed, t->v4daddr > x->v4daddr for any * x in p->avl_left subtree. @@ -314,8 +313,7 @@ static void unlink_from_pool(struct inet_peer *p) t->avl_left = p->avl_left; t->avl_right = p->avl_right; t->avl_height = p->avl_height; - if (delp[1] != &p->avl_left) - BUG(); + BUG_ON(delp[1] != &p->avl_left); delp[1] = &t->avl_left; /* was &p->avl_left */ } peer_avl_rebalance(stack, stackptr); diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 0a46123..a97ed54 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -3347,7 +3347,7 @@ tcp_collapse(struct sock *sk, struct sk_buff_head *list, int offset = start - TCP_SKB_CB(skb)->seq; int size = TCP_SKB_CB(skb)->end_seq - start; - if (offset < 0) BUG(); + BUG_ON(offset < 0); if (size > 0) { size = min(copy, size); if (skb_copy_bits(skb, offset, skb_put(nskb, size), size)) diff --git a/net/key/af_key.c b/net/key/af_key.c index 52efd04..4c2f6d6 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -297,8 +297,7 @@ static int pfkey_error(struct sadb_msg *orig, int err, struct sock *sk) err = EINTR; if (err >= 512) err = EINVAL; - if (err <= 0 || err >= 256) - BUG(); + BUG_ON(err <= 0 || err >= 256); hdr = (struct sadb_msg *) skb_put(skb, sizeof(struct sadb_msg)); pfkey_hdr_dup(hdr, orig); diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index 2d7d8a5..b8b38ab 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c @@ -1250,8 +1250,7 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, case SCTP_CMD_TIMER_START: timer = &asoc->timers[cmd->obj.to]; timeout = asoc->timeouts[cmd->obj.to]; - if (!timeout) - BUG(); + BUG_ON(!timeout); timer->expires = jiffies + timeout; sctp_association_hold(asoc); diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c index f509e99..dcaa0c4 100644 --- a/net/sunrpc/cache.c +++ b/net/sunrpc/cache.c @@ -575,12 +575,11 @@ cache_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos) if (rp->q.list.next == &cd->queue) { spin_unlock(&queue_lock); up(&queue_io_sem); - if (rp->offset) - BUG(); + BUG_ON(rp->offset); return 0; } rq = container_of(rp->q.list.next, struct cache_request, q.list); - if (rq->q.reader) BUG(); + BUG_ON(rq->q.reader); if (rp->offset == 0) rq->readers++; spin_unlock(&queue_lock); diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c index e4296c8..b19cc26 100644 --- a/net/sunrpc/svc.c +++ b/net/sunrpc/svc.c @@ -122,8 +122,7 @@ svc_init_buffer(struct svc_rqst *rqstp, unsigned int size) rqstp->rq_argused = 0; rqstp->rq_resused = 0; arghi = 0; - if (pages > RPCSVC_MAXPAGES) - BUG(); + BUG_ON(pages > RPCSVC_MAXPAGES); while (pages) { struct page *p = alloc_page(GFP_KERNEL); if (!p) diff --git a/net/xfrm/xfrm_algo.c b/net/xfrm/xfrm_algo.c index 2f4531f..6ed3302 100644 --- a/net/xfrm/xfrm_algo.c +++ b/net/xfrm/xfrm_algo.c @@ -540,8 +540,7 @@ void skb_icv_walk(const struct sk_buff *skb, struct crypto_tfm *tfm, start = end; } } - if (len) - BUG(); + BUG_ON(len); } EXPORT_SYMBOL_GPL(skb_icv_walk); @@ -610,8 +609,7 @@ skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset, int len) start = end; } } - if (len) - BUG(); + BUG_ON(len); return elt; } EXPORT_SYMBOL_GPL(skb_to_sgvec); diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 59614a9..077bbf9 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -248,11 +248,9 @@ EXPORT_SYMBOL(xfrm_policy_alloc); void __xfrm_policy_destroy(struct xfrm_policy *policy) { - if (!policy->dead) - BUG(); + BUG_ON(!policy->dead); - if (policy->bundles) - BUG(); + BUG_ON(policy->bundles); if (del_timer(&policy->timer)) BUG(); -- cgit v1.1 From c1854ebc7f13b23c3d6a6e641a1a1db1116ca998 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Sun, 8 Jan 2006 22:31:04 -0800 Subject: [AX25] mkiss: Drop spinlock before sleeping call. With the previous missing-unlock fix the spinlock is dropped only after the tty->driver->write() call which might sleep. Signed-off-by: Ralf Baechle Signed-off-by: David S. Miller --- drivers/net/hamradio/mkiss.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c index 41b3d83..f4424cf 100644 --- a/drivers/net/hamradio/mkiss.c +++ b/drivers/net/hamradio/mkiss.c @@ -515,6 +515,7 @@ static void ax_encaps(struct net_device *dev, unsigned char *icp, int len) count = kiss_esc(p, (unsigned char *)ax->xbuff, len); } } + spin_unlock_bh(&ax->buflock); set_bit(TTY_DO_WRITE_WAKEUP, &ax->tty->flags); actual = ax->tty->driver->write(ax->tty, ax->xbuff, count); @@ -524,7 +525,6 @@ static void ax_encaps(struct net_device *dev, unsigned char *icp, int len) ax->dev->trans_start = jiffies; ax->xleft = count - actual; ax->xhead = ax->xbuff + actual; - spin_unlock_bh(&ax->buflock); } /* Encapsulate an AX.25 packet and kick it into a TTY queue. */ -- cgit v1.1 From 253af4235d24ddfcd9f5403485e9273b33d8fa5e Mon Sep 17 00:00:00 2001 From: Jamal Hadi Salim Date: Sun, 8 Jan 2006 22:34:25 -0800 Subject: [NET]: Add IFB (Intermediate Functional Block) network device. A new device to do intermidiate functional block in a system shared manner. To use the new functionality, you need to turn on qos/classifier actions. The new functionality can be grouped as: 1) qdiscs/policies that are per device as opposed to system wide. ifb allows for a device which can be redirected to thus providing an impression of sharing. 2) Allows for queueing incoming traffic for shaping instead of dropping. Packets are redirected to this device using tc/action mirred redirect construct. If they are sent to it by plain routing instead then they will merely be dropped and the stats would indicate that. Signed-off-by: Jamal Hadi Salim Signed-off-by: David S. Miller --- drivers/net/Kconfig | 13 +++ drivers/net/Makefile | 1 + drivers/net/ifb.c | 294 +++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 308 insertions(+) create mode 100644 drivers/net/ifb.c diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 733bc25..4959800 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -27,6 +27,19 @@ config NETDEVICES # that for each of the symbols. if NETDEVICES +config IFB + tristate "Intermediate Functional Block support" + depends on NET_CLS_ACT + ---help--- + This is an intermidiate driver that allows sharing of + resources. + To compile this driver as a module, choose M here: the module + will be called ifb. If you want to use more than one ifb + device at a time, you need to compile this driver as a module. + Instead of 'ifb', the devices will then be called 'ifb0', + 'ifb1' etc. + Look at the iproute2 documentation directory for usage etc + config DUMMY tristate "Dummy net driver support" ---help--- diff --git a/drivers/net/Makefile b/drivers/net/Makefile index b74a7cb..00e72b1 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -125,6 +125,7 @@ ifeq ($(CONFIG_SLIP_COMPRESSED),y) endif obj-$(CONFIG_DUMMY) += dummy.o +obj-$(CONFIG_IFB) += ifb.o obj-$(CONFIG_DE600) += de600.o obj-$(CONFIG_DE620) += de620.o obj-$(CONFIG_LANCE) += lance.o diff --git a/drivers/net/ifb.c b/drivers/net/ifb.c new file mode 100644 index 0000000..1b69925 --- /dev/null +++ b/drivers/net/ifb.c @@ -0,0 +1,294 @@ +/* drivers/net/ifb.c: + + The purpose of this driver is to provide a device that allows + for sharing of resources: + + 1) qdiscs/policies that are per device as opposed to system wide. + ifb allows for a device which can be redirected to thus providing + an impression of sharing. + + 2) Allows for queueing incoming traffic for shaping instead of + dropping. + + The original concept is based on what is known as the IMQ + driver initially written by Martin Devera, later rewritten + by Patrick McHardy and then maintained by Andre Correa. + + You need the tc action mirror or redirect to feed this device + packets. + + 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 (at your option) any later version. + + Authors: Jamal Hadi Salim (2005) + +*/ + + +#include +#include +#include +#include +#include +#include +#include +#include + +#define TX_TIMEOUT (2*HZ) + +#define TX_Q_LIMIT 32 +struct ifb_private { + struct net_device_stats stats; + struct tasklet_struct ifb_tasklet; + int tasklet_pending; + /* mostly debug stats leave in for now */ + unsigned long st_task_enter; /* tasklet entered */ + unsigned long st_txq_refl_try; /* transmit queue refill attempt */ + unsigned long st_rxq_enter; /* receive queue entered */ + unsigned long st_rx2tx_tran; /* receive to trasmit transfers */ + unsigned long st_rxq_notenter; /*receiveQ not entered, resched */ + unsigned long st_rx_frm_egr; /* received from egress path */ + unsigned long st_rx_frm_ing; /* received from ingress path */ + unsigned long st_rxq_check; + unsigned long st_rxq_rsch; + struct sk_buff_head rq; + struct sk_buff_head tq; +}; + +static int numifbs = 1; + +static void ri_tasklet(unsigned long dev); +static int ifb_xmit(struct sk_buff *skb, struct net_device *dev); +static struct net_device_stats *ifb_get_stats(struct net_device *dev); +static int ifb_open(struct net_device *dev); +static int ifb_close(struct net_device *dev); + +static void ri_tasklet(unsigned long dev) +{ + + struct net_device *_dev = (struct net_device *)dev; + struct ifb_private *dp = netdev_priv(_dev); + struct net_device_stats *stats = &dp->stats; + struct sk_buff *skb; + + dp->st_task_enter++; + if ((skb = skb_peek(&dp->tq)) == NULL) { + dp->st_txq_refl_try++; + if (spin_trylock(&_dev->xmit_lock)) { + dp->st_rxq_enter++; + while ((skb = skb_dequeue(&dp->rq)) != NULL) { + skb_queue_tail(&dp->tq, skb); + dp->st_rx2tx_tran++; + } + spin_unlock(&_dev->xmit_lock); + } else { + /* reschedule */ + dp->st_rxq_notenter++; + goto resched; + } + } + + while ((skb = skb_dequeue(&dp->tq)) != NULL) { + u32 from = G_TC_FROM(skb->tc_verd); + + skb->tc_verd = 0; + skb->tc_verd = SET_TC_NCLS(skb->tc_verd); + stats->tx_packets++; + stats->tx_bytes +=skb->len; + if (from & AT_EGRESS) { + dp->st_rx_frm_egr++; + dev_queue_xmit(skb); + } else if (from & AT_INGRESS) { + + dp->st_rx_frm_ing++; + netif_rx(skb); + } else { + dev_kfree_skb(skb); + stats->tx_dropped++; + } + } + + if (spin_trylock(&_dev->xmit_lock)) { + dp->st_rxq_check++; + if ((skb = skb_peek(&dp->rq)) == NULL) { + dp->tasklet_pending = 0; + if (netif_queue_stopped(_dev)) + netif_wake_queue(_dev); + } else { + dp->st_rxq_rsch++; + spin_unlock(&_dev->xmit_lock); + goto resched; + } + spin_unlock(&_dev->xmit_lock); + } else { +resched: + dp->tasklet_pending = 1; + tasklet_schedule(&dp->ifb_tasklet); + } + +} + +static void __init ifb_setup(struct net_device *dev) +{ + /* Initialize the device structure. */ + dev->get_stats = ifb_get_stats; + dev->hard_start_xmit = ifb_xmit; + dev->open = &ifb_open; + dev->stop = &ifb_close; + + /* Fill in device structure with ethernet-generic values. */ + ether_setup(dev); + dev->tx_queue_len = TX_Q_LIMIT; + dev->change_mtu = NULL; + dev->flags |= IFF_NOARP; + dev->flags &= ~IFF_MULTICAST; + SET_MODULE_OWNER(dev); + random_ether_addr(dev->dev_addr); +} + +static int ifb_xmit(struct sk_buff *skb, struct net_device *dev) +{ + struct ifb_private *dp = netdev_priv(dev); + struct net_device_stats *stats = &dp->stats; + int ret = 0; + u32 from = G_TC_FROM(skb->tc_verd); + + stats->tx_packets++; + stats->tx_bytes+=skb->len; + + if (!from || !skb->input_dev) { +dropped: + dev_kfree_skb(skb); + stats->rx_dropped++; + return ret; + } else { + /* + * note we could be going + * ingress -> egress or + * egress -> ingress + */ + skb->dev = skb->input_dev; + skb->input_dev = dev; + if (from & AT_INGRESS) { + skb_pull(skb, skb->dev->hard_header_len); + } else { + if (!(from & AT_EGRESS)) { + goto dropped; + } + } + } + + if (skb_queue_len(&dp->rq) >= dev->tx_queue_len) { + netif_stop_queue(dev); + } + + dev->trans_start = jiffies; + skb_queue_tail(&dp->rq, skb); + if (!dp->tasklet_pending) { + dp->tasklet_pending = 1; + tasklet_schedule(&dp->ifb_tasklet); + } + + return ret; +} + +static struct net_device_stats *ifb_get_stats(struct net_device *dev) +{ + struct ifb_private *dp = netdev_priv(dev); + struct net_device_stats *stats = &dp->stats; + + pr_debug("tasklets stats %ld:%ld:%ld:%ld:%ld:%ld:%ld:%ld:%ld \n", + dp->st_task_enter, dp->st_txq_refl_try, dp->st_rxq_enter, + dp->st_rx2tx_tran dp->st_rxq_notenter, dp->st_rx_frm_egr, + dp->st_rx_frm_ing, dp->st_rxq_check, dp->st_rxq_rsch ); + + return stats; +} + +static struct net_device **ifbs; + +/* Number of ifb devices to be set up by this module. */ +module_param(numifbs, int, 0); +MODULE_PARM_DESC(numifbs, "Number of ifb devices"); + +static int ifb_close(struct net_device *dev) +{ + struct ifb_private *dp = netdev_priv(dev); + + tasklet_kill(&dp->ifb_tasklet); + netif_stop_queue(dev); + skb_queue_purge(&dp->rq); + skb_queue_purge(&dp->tq); + return 0; +} + +static int ifb_open(struct net_device *dev) +{ + struct ifb_private *dp = netdev_priv(dev); + + tasklet_init(&dp->ifb_tasklet, ri_tasklet, (unsigned long)dev); + skb_queue_head_init(&dp->rq); + skb_queue_head_init(&dp->tq); + netif_start_queue(dev); + + return 0; +} + +static int __init ifb_init_one(int index) +{ + struct net_device *dev_ifb; + int err; + + dev_ifb = alloc_netdev(sizeof(struct ifb_private), + "ifb%d", ifb_setup); + + if (!dev_ifb) + return -ENOMEM; + + if ((err = register_netdev(dev_ifb))) { + free_netdev(dev_ifb); + dev_ifb = NULL; + } else { + ifbs[index] = dev_ifb; + } + + return err; +} + +static void ifb_free_one(int index) +{ + unregister_netdev(ifbs[index]); + free_netdev(ifbs[index]); +} + +static int __init ifb_init_module(void) +{ + int i, err = 0; + ifbs = kmalloc(numifbs * sizeof(void *), GFP_KERNEL); + if (!ifbs) + return -ENOMEM; + for (i = 0; i < numifbs && !err; i++) + err = ifb_init_one(i); + if (err) { + while (--i >= 0) + ifb_free_one(i); + } + + return err; +} + +static void __exit ifb_cleanup_module(void) +{ + int i; + + for (i = 0; i < numifbs; i++) + ifb_free_one(i); + kfree(ifbs); +} + +module_init(ifb_init_module); +module_exit(ifb_cleanup_module); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Jamal Hadi Salim"); -- cgit v1.1 From 29f1df6cc1c3ee3530939f0e38d80a9b50645ba5 Mon Sep 17 00:00:00 2001 From: Jamal Hadi Salim Date: Sun, 8 Jan 2006 22:35:55 -0800 Subject: [PKT_SCHED]: Fix qdisc return code. The mapping between TC_ACTION_SHOT and the qdisc return codes is better suited to NET_XMIT_BYPASS so as not to confuse TCP Signed-off-by: Jamal Hadi Salim Signed-off-by: David S. Miller --- net/sched/sch_cbq.c | 4 ++-- net/sched/sch_hfsc.c | 4 ++-- net/sched/sch_htb.c | 4 ++-- net/sched/sch_prio.c | 7 ++++--- 4 files changed, 10 insertions(+), 9 deletions(-) diff --git a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c index 09453f9..6cd8170 100644 --- a/net/sched/sch_cbq.c +++ b/net/sched/sch_cbq.c @@ -257,7 +257,7 @@ cbq_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr) (cl = cbq_class_lookup(q, prio)) != NULL) return cl; - *qerr = NET_XMIT_DROP; + *qerr = NET_XMIT_BYPASS; for (;;) { int result = 0; defmap = head->defaults; @@ -413,7 +413,7 @@ cbq_enqueue(struct sk_buff *skb, struct Qdisc *sch) q->rx_class = cl; #endif if (cl == NULL) { - if (ret == NET_XMIT_DROP) + if (ret == NET_XMIT_BYPASS) sch->qstats.drops++; kfree_skb(skb); return ret; diff --git a/net/sched/sch_hfsc.c b/net/sched/sch_hfsc.c index cad1758..91132f6 100644 --- a/net/sched/sch_hfsc.c +++ b/net/sched/sch_hfsc.c @@ -1227,7 +1227,7 @@ hfsc_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr) if (cl->level == 0) return cl; - *qerr = NET_XMIT_DROP; + *qerr = NET_XMIT_BYPASS; tcf = q->root.filter_list; while (tcf && (result = tc_classify(skb, tcf, &res)) >= 0) { #ifdef CONFIG_NET_CLS_ACT @@ -1643,7 +1643,7 @@ hfsc_enqueue(struct sk_buff *skb, struct Qdisc *sch) cl = hfsc_classify(skb, sch, &err); if (cl == NULL) { - if (err == NET_XMIT_DROP) + if (err == NET_XMIT_BYPASS) sch->qstats.drops++; kfree_skb(skb); return err; diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c index 558cc08..3ec95df 100644 --- a/net/sched/sch_htb.c +++ b/net/sched/sch_htb.c @@ -321,7 +321,7 @@ static struct htb_class *htb_classify(struct sk_buff *skb, struct Qdisc *sch, in if ((cl = htb_find(skb->priority,sch)) != NULL && cl->level == 0) return cl; - *qerr = NET_XMIT_DROP; + *qerr = NET_XMIT_BYPASS; tcf = q->filter_list; while (tcf && (result = tc_classify(skb, tcf, &res)) >= 0) { #ifdef CONFIG_NET_CLS_ACT @@ -724,7 +724,7 @@ static int htb_enqueue(struct sk_buff *skb, struct Qdisc *sch) } #ifdef CONFIG_NET_CLS_ACT } else if (!cl) { - if (ret == NET_XMIT_DROP) + if (ret == NET_XMIT_BYPASS) sch->qstats.drops++; kfree_skb (skb); return ret; diff --git a/net/sched/sch_prio.c b/net/sched/sch_prio.c index 3ac0f49..5b3a3e4 100644 --- a/net/sched/sch_prio.c +++ b/net/sched/sch_prio.c @@ -54,7 +54,7 @@ prio_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr) u32 band = skb->priority; struct tcf_result res; - *qerr = NET_XMIT_DROP; + *qerr = NET_XMIT_BYPASS; if (TC_H_MAJ(skb->priority) != sch->handle) { #ifdef CONFIG_NET_CLS_ACT switch (tc_classify(skb, q->filter_list, &res)) { @@ -91,7 +91,8 @@ prio_enqueue(struct sk_buff *skb, struct Qdisc *sch) qdisc = prio_classify(skb, sch, &ret); #ifdef CONFIG_NET_CLS_ACT if (qdisc == NULL) { - if (ret == NET_XMIT_DROP) + + if (ret == NET_XMIT_BYPASS) sch->qstats.drops++; kfree_skb(skb); return ret; @@ -118,7 +119,7 @@ prio_requeue(struct sk_buff *skb, struct Qdisc* sch) qdisc = prio_classify(skb, sch, &ret); #ifdef CONFIG_NET_CLS_ACT if (qdisc == NULL) { - if (ret == NET_XMIT_DROP) + if (ret == NET_XMIT_BYPASS) sch->qstats.drops++; kfree_skb(skb); return ret; -- cgit v1.1 From cfacb0577e319b02ed42685a0a8e0f1657ac461b Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Sun, 8 Jan 2006 22:36:54 -0800 Subject: [IPV4]: ip_output.c needs xfrm.h This patch fixes a warning from my IPsec patches: CC net/ipv4/ip_output.o net/ipv4/ip_output.c: In function 'ip_finish_output': net/ipv4/ip_output.c:208: warning: implicit declaration of function 'xfrm4_output_finish' Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/ipv4/ip_output.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index c2169b4..3324fbf 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -69,6 +69,7 @@ #include #include #include +#include #include #include #include -- cgit v1.1 From a2c2064f7f23fde23e34fb5d07de43b582966b71 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Sun, 8 Jan 2006 22:37:26 -0800 Subject: [IPV6]: Set skb->priority in ip6_output.c Set skb->priority = sk->sk_priority as in raw.c and IPv4. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/ipv6/ip6_output.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index b4c4beb..efa3e72 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -226,6 +226,8 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl, ipv6_addr_copy(&hdr->saddr, &fl->fl6_src); ipv6_addr_copy(&hdr->daddr, first_hop); + skb->priority = sk->sk_priority; + mtu = dst_mtu(dst); if ((skb->len <= mtu) || ipfragok) { IP6_INC_STATS(IPSTATS_MIB_OUTREQUESTS); @@ -1182,6 +1184,8 @@ int ip6_push_pending_frames(struct sock *sk) ipv6_addr_copy(&hdr->saddr, &fl->fl6_src); ipv6_addr_copy(&hdr->daddr, final_dst); + skb->priority = sk->sk_priority; + skb->dst = dst_clone(&rt->u.dst); IP6_INC_STATS(IPSTATS_MIB_OUTREQUESTS); err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, skb->dst->dev, dst_output); -- cgit v1.1 From 7dbf0755249336f44f57368bdbf6f84103b3ba75 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 9 Jan 2006 14:56:03 -0800 Subject: [INET_DIAG]: Use inet_twsk() with TIME_WAIT sockets The fields being accessed in inet_diag_dump are outside sock_common, the common part of struct sock and struct inet_timewait_sock. Signed-off-by: Arnaldo Carvalho de Melo Signed-off-by: David S. Miller --- net/ipv4/inet_diag.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c index c499081..c3b3348 100644 --- a/net/ipv4/inet_diag.c +++ b/net/ipv4/inet_diag.c @@ -697,14 +697,14 @@ next_normal: if (r->idiag_states & TCPF_TIME_WAIT) { sk_for_each(sk, node, &hashinfo->ehash[i + hashinfo->ehash_size].chain) { - struct inet_sock *inet = inet_sk(sk); + const struct inet_timewait_sock *tw = inet_twsk(sk); if (num < s_num) goto next_dying; - if (r->id.idiag_sport != inet->sport && + if (r->id.idiag_sport != tw->tw_sport && r->id.idiag_sport) goto next_dying; - if (r->id.idiag_dport != inet->dport && + if (r->id.idiag_dport != tw->tw_dport && r->id.idiag_dport) goto next_dying; if (inet_diag_dump_sock(skb, sk, cb) < 0) { -- cgit v1.1 From 4e852c027989c9fd5c51fb0080e28590c35c75ba Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 9 Jan 2006 14:56:19 -0800 Subject: [INET_DIAG]: whitespace/simple cleanups Signed-off-by: Arnaldo Carvalho de Melo Signed-off-by: David S. Miller --- net/ipv4/inet_diag.c | 57 ++++++++++++++++++++++++++-------------------------- 1 file changed, 28 insertions(+), 29 deletions(-) diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c index c3b3348..4c4ae4a 100644 --- a/net/ipv4/inet_diag.c +++ b/net/ipv4/inet_diag.c @@ -51,8 +51,8 @@ static struct sock *idiagnl; RTA_DATA(__RTA_PUT(skb, attrtype, attrlen)) static int inet_diag_fill(struct sk_buff *skb, struct sock *sk, - int ext, u32 pid, u32 seq, u16 nlmsg_flags, - const struct nlmsghdr *unlh) + int ext, u32 pid, u32 seq, u16 nlmsg_flags, + const struct nlmsghdr *unlh) { const struct inet_sock *inet = inet_sk(sk); const struct inet_connection_sock *icsk = inet_csk(sk); @@ -77,7 +77,7 @@ static int inet_diag_fill(struct sk_buff *skb, struct sock *sk, if (ext & (1 << (INET_DIAG_INFO - 1))) info = INET_DIAG_PUT(skb, INET_DIAG_INFO, handler->idiag_info_size); - + if ((ext & (1 << (INET_DIAG_CONG - 1))) && icsk->icsk_ca_ops) { size_t len = strlen(icsk->icsk_ca_ops->name); strcpy(INET_DIAG_PUT(skb, INET_DIAG_CONG, len + 1), @@ -185,7 +185,8 @@ nlmsg_failure: return -1; } -static int inet_diag_get_exact(struct sk_buff *in_skb, const struct nlmsghdr *nlh) +static int inet_diag_get_exact(struct sk_buff *in_skb, + const struct nlmsghdr *nlh) { int err; struct sock *sk; @@ -283,7 +284,7 @@ static int bitstring_match(const u32 *a1, const u32 *a2, int bits) static int inet_diag_bc_run(const void *bc, int len, - const struct inet_diag_entry *entry) + const struct inet_diag_entry *entry) { while (len > 0) { int yes = 1; @@ -322,7 +323,7 @@ static int inet_diag_bc_run(const void *bc, int len, yes = 0; break; } - + if (cond->prefix_len == 0) break; @@ -331,7 +332,8 @@ static int inet_diag_bc_run(const void *bc, int len, else addr = entry->daddr; - if (bitstring_match(addr, cond->addr, cond->prefix_len)) + if (bitstring_match(addr, cond->addr, + cond->prefix_len)) break; if (entry->family == AF_INET6 && cond->family == AF_INET) { @@ -346,7 +348,7 @@ static int inet_diag_bc_run(const void *bc, int len, } } - if (yes) { + if (yes) { len -= op->yes; bc += op->yes; } else { @@ -407,14 +409,14 @@ static int inet_diag_bc_audit(const void *bytecode, int bytecode_len) default: return -EINVAL; } - bc += op->yes; + bc += op->yes; len -= op->yes; } return len == 0 ? 0 : -EINVAL; } static int inet_diag_dump_sock(struct sk_buff *skb, struct sock *sk, - struct netlink_callback *cb) + struct netlink_callback *cb) { struct inet_diag_req *r = NLMSG_DATA(cb->nlh); @@ -445,13 +447,12 @@ static int inet_diag_dump_sock(struct sk_buff *skb, struct sock *sk, } return inet_diag_fill(skb, sk, r->idiag_ext, NETLINK_CB(cb->skb).pid, - cb->nlh->nlmsg_seq, NLM_F_MULTI, cb->nlh); + cb->nlh->nlmsg_seq, NLM_F_MULTI, cb->nlh); } static int inet_diag_fill_req(struct sk_buff *skb, struct sock *sk, - struct request_sock *req, - u32 pid, u32 seq, - const struct nlmsghdr *unlh) + struct request_sock *req, u32 pid, u32 seq, + const struct nlmsghdr *unlh) { const struct inet_request_sock *ireq = inet_rsk(req); struct inet_sock *inet = inet_sk(sk); @@ -504,7 +505,7 @@ nlmsg_failure: } static int inet_diag_dump_reqs(struct sk_buff *skb, struct sock *sk, - struct netlink_callback *cb) + struct netlink_callback *cb) { struct inet_diag_entry entry; struct inet_diag_req *r = NLMSG_DATA(cb->nlh); @@ -556,7 +557,7 @@ static int inet_diag_dump_reqs(struct sk_buff *skb, struct sock *sk, inet6_rsk(req)->loc_addr.s6_addr32 : #endif &ireq->loc_addr; - entry.daddr = + entry.daddr = #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) (entry.family == AF_INET6) ? inet6_rsk(req)->rmt_addr.s6_addr32 : @@ -599,7 +600,7 @@ static int inet_diag_dump(struct sk_buff *skb, struct netlink_callback *cb) handler = inet_diag_table[cb->nlh->nlmsg_type]; BUG_ON(handler == NULL); hashinfo = handler->idiag_hashinfo; - + s_i = cb->args[1]; s_num = num = cb->args[2]; @@ -672,7 +673,6 @@ skip_listen_ht: s_num = 0; read_lock_bh(&head->lock); - num = 0; sk_for_each(sk, node, &head->chain) { struct inet_sock *inet = inet_sk(sk); @@ -684,7 +684,8 @@ skip_listen_ht: if (r->id.idiag_sport != inet->sport && r->id.idiag_sport) goto next_normal; - if (r->id.idiag_dport != inet->dport && r->id.idiag_dport) + if (r->id.idiag_dport != inet->dport && + r->id.idiag_dport) goto next_normal; if (inet_diag_dump_sock(skb, sk, cb) < 0) { read_unlock_bh(&head->lock); @@ -724,8 +725,7 @@ done: return skb->len; } -static __inline__ int -inet_diag_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) +static inline int inet_diag_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) { if (!(nlh->nlmsg_flags&NLM_F_REQUEST)) return 0; @@ -755,9 +755,8 @@ inet_diag_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) } return netlink_dump_start(idiagnl, skb, nlh, inet_diag_dump, NULL); - } else { + } else return inet_diag_get_exact(skb, nlh); - } err_inval: return -EINVAL; @@ -766,15 +765,15 @@ err_inval: static inline void inet_diag_rcv_skb(struct sk_buff *skb) { - int err; - struct nlmsghdr * nlh; - if (skb->len >= NLMSG_SPACE(0)) { - nlh = (struct nlmsghdr *)skb->data; - if (nlh->nlmsg_len < sizeof(*nlh) || skb->len < nlh->nlmsg_len) + int err; + struct nlmsghdr *nlh = (struct nlmsghdr *)skb->data; + + if (nlh->nlmsg_len < sizeof(*nlh) || + skb->len < nlh->nlmsg_len) return; err = inet_diag_rcv_msg(skb, nlh); - if (err || nlh->nlmsg_flags & NLM_F_ACK) + if (err || nlh->nlmsg_flags & NLM_F_ACK) netlink_ack(skb, nlh, err); } } -- cgit v1.1 From c7d58aabdc08aea92d6c5e01dcd7473a74b3642c Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 9 Jan 2006 14:56:38 -0800 Subject: [INET_DIAG]: Introduce inet_twsk_diag_dump & inet_twsk_diag_fill To properly dump TIME_WAIT sockets and to reduce complexity a bit by having per socket class accessor routines. Signed-off-by: Arnaldo Carvalho de Melo Signed-off-by: David S. Miller --- net/ipv4/inet_diag.c | 158 ++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 111 insertions(+), 47 deletions(-) diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c index 4c4ae4a..985c573 100644 --- a/net/ipv4/inet_diag.c +++ b/net/ipv4/inet_diag.c @@ -70,20 +70,22 @@ static int inet_diag_fill(struct sk_buff *skb, struct sock *sk, nlh->nlmsg_flags = nlmsg_flags; r = NLMSG_DATA(nlh); - if (sk->sk_state != TCP_TIME_WAIT) { - if (ext & (1 << (INET_DIAG_MEMINFO - 1))) - minfo = INET_DIAG_PUT(skb, INET_DIAG_MEMINFO, - sizeof(*minfo)); - if (ext & (1 << (INET_DIAG_INFO - 1))) - info = INET_DIAG_PUT(skb, INET_DIAG_INFO, - handler->idiag_info_size); - - if ((ext & (1 << (INET_DIAG_CONG - 1))) && icsk->icsk_ca_ops) { - size_t len = strlen(icsk->icsk_ca_ops->name); - strcpy(INET_DIAG_PUT(skb, INET_DIAG_CONG, len + 1), - icsk->icsk_ca_ops->name); - } + BUG_ON(sk->sk_state == TCP_TIME_WAIT); + + if (ext & (1 << (INET_DIAG_MEMINFO - 1))) + minfo = INET_DIAG_PUT(skb, INET_DIAG_MEMINFO, sizeof(*minfo)); + + if (ext & (1 << (INET_DIAG_INFO - 1))) + info = INET_DIAG_PUT(skb, INET_DIAG_INFO, + handler->idiag_info_size); + + if ((ext & (1 << (INET_DIAG_CONG - 1))) && icsk->icsk_ca_ops) { + const size_t len = strlen(icsk->icsk_ca_ops->name); + + strcpy(INET_DIAG_PUT(skb, INET_DIAG_CONG, len + 1), + icsk->icsk_ca_ops->name); } + r->idiag_family = sk->sk_family; r->idiag_state = sk->sk_state; r->idiag_timer = 0; @@ -93,37 +95,6 @@ static int inet_diag_fill(struct sk_buff *skb, struct sock *sk, r->id.idiag_cookie[0] = (u32)(unsigned long)sk; r->id.idiag_cookie[1] = (u32)(((unsigned long)sk >> 31) >> 1); - if (r->idiag_state == TCP_TIME_WAIT) { - const struct inet_timewait_sock *tw = inet_twsk(sk); - long tmo = tw->tw_ttd - jiffies; - if (tmo < 0) - tmo = 0; - - r->id.idiag_sport = tw->tw_sport; - r->id.idiag_dport = tw->tw_dport; - r->id.idiag_src[0] = tw->tw_rcv_saddr; - r->id.idiag_dst[0] = tw->tw_daddr; - r->idiag_state = tw->tw_substate; - r->idiag_timer = 3; - r->idiag_expires = (tmo * 1000 + HZ - 1) / HZ; - r->idiag_rqueue = 0; - r->idiag_wqueue = 0; - r->idiag_uid = 0; - r->idiag_inode = 0; -#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) - if (r->idiag_family == AF_INET6) { - const struct inet6_timewait_sock *tw6 = inet6_twsk(sk); - - ipv6_addr_copy((struct in6_addr *)r->id.idiag_src, - &tw6->tw_v6_rcv_saddr); - ipv6_addr_copy((struct in6_addr *)r->id.idiag_dst, - &tw6->tw_v6_daddr); - } -#endif - nlh->nlmsg_len = skb->tail - b; - return skb->len; - } - r->id.idiag_sport = inet->sport; r->id.idiag_dport = inet->dport; r->id.idiag_src[0] = inet->rcv_saddr; @@ -185,6 +156,62 @@ nlmsg_failure: return -1; } +static int inet_twsk_diag_fill(struct inet_timewait_sock *tw, + struct sk_buff *skb, int ext, u32 pid, + u32 seq, u16 nlmsg_flags, + const struct nlmsghdr *unlh) +{ + long tmo; + struct inet_diag_msg *r; + const unsigned char *previous_tail = skb->tail; + struct nlmsghdr *nlh = NLMSG_PUT(skb, pid, seq, + unlh->nlmsg_type, sizeof(*r)); + + r = NLMSG_DATA(nlh); + BUG_ON(tw->tw_state != TCP_TIME_WAIT); + + nlh->nlmsg_flags = nlmsg_flags; + + tmo = tw->tw_ttd - jiffies; + if (tmo < 0) + tmo = 0; + + r->idiag_family = tw->tw_family; + r->idiag_state = tw->tw_state; + r->idiag_timer = 0; + r->idiag_retrans = 0; + r->id.idiag_if = tw->tw_bound_dev_if; + r->id.idiag_cookie[0] = (u32)(unsigned long)tw; + r->id.idiag_cookie[1] = (u32)(((unsigned long)tw >> 31) >> 1); + r->id.idiag_sport = tw->tw_sport; + r->id.idiag_dport = tw->tw_dport; + r->id.idiag_src[0] = tw->tw_rcv_saddr; + r->id.idiag_dst[0] = tw->tw_daddr; + r->idiag_state = tw->tw_substate; + r->idiag_timer = 3; + r->idiag_expires = (tmo * 1000 + HZ - 1) / HZ; + r->idiag_rqueue = 0; + r->idiag_wqueue = 0; + r->idiag_uid = 0; + r->idiag_inode = 0; +#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) + if (tw->tw_family == AF_INET6) { + const struct inet6_timewait_sock *tw6 = + inet6_twsk((struct sock *)tw); + + ipv6_addr_copy((struct in6_addr *)r->id.idiag_src, + &tw6->tw_v6_rcv_saddr); + ipv6_addr_copy((struct in6_addr *)r->id.idiag_dst, + &tw6->tw_v6_daddr); + } +#endif + nlh->nlmsg_len = skb->tail - previous_tail; + return skb->len; +nlmsg_failure: + skb_trim(skb, previous_tail - skb->data); + return -1; +} + static int inet_diag_get_exact(struct sk_buff *in_skb, const struct nlmsghdr *nlh) { @@ -450,6 +477,42 @@ static int inet_diag_dump_sock(struct sk_buff *skb, struct sock *sk, cb->nlh->nlmsg_seq, NLM_F_MULTI, cb->nlh); } +static int inet_twsk_diag_dump(struct inet_timewait_sock *tw, + struct sk_buff *skb, + struct netlink_callback *cb) +{ + struct inet_diag_req *r = NLMSG_DATA(cb->nlh); + + if (cb->nlh->nlmsg_len > 4 + NLMSG_SPACE(sizeof(*r))) { + struct inet_diag_entry entry; + struct rtattr *bc = (struct rtattr *)(r + 1); + + entry.family = tw->tw_family; +#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) + if (tw->tw_family == AF_INET6) { + struct inet6_timewait_sock *tw6 = + inet6_twsk((struct sock *)tw); + entry.saddr = tw6->tw_v6_rcv_saddr.s6_addr32; + entry.daddr = tw6->tw_v6_daddr.s6_addr32; + } else +#endif + { + entry.saddr = &tw->tw_rcv_saddr; + entry.daddr = &tw->tw_daddr; + } + entry.sport = tw->tw_num; + entry.dport = ntohs(tw->tw_dport); + entry.userlocks = 0; + + if (!inet_diag_bc_run(RTA_DATA(bc), RTA_PAYLOAD(bc), &entry)) + return 0; + } + + return inet_twsk_diag_fill(tw, skb, r->idiag_ext, + NETLINK_CB(cb->skb).pid, + cb->nlh->nlmsg_seq, NLM_F_MULTI, cb->nlh); +} + static int inet_diag_fill_req(struct sk_buff *skb, struct sock *sk, struct request_sock *req, u32 pid, u32 seq, const struct nlmsghdr *unlh) @@ -696,9 +759,10 @@ next_normal: } if (r->idiag_states & TCPF_TIME_WAIT) { - sk_for_each(sk, node, + struct inet_timewait_sock *tw; + + inet_twsk_for_each(tw, node, &hashinfo->ehash[i + hashinfo->ehash_size].chain) { - const struct inet_timewait_sock *tw = inet_twsk(sk); if (num < s_num) goto next_dying; @@ -708,7 +772,7 @@ next_normal: if (r->id.idiag_dport != tw->tw_dport && r->id.idiag_dport) goto next_dying; - if (inet_diag_dump_sock(skb, sk, cb) < 0) { + if (inet_twsk_diag_dump(tw, skb, cb) < 0) { read_unlock_bh(&head->lock); goto done; } -- cgit v1.1 From dff2c03534f525813342ab8dec90c5bb1ee07471 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 9 Jan 2006 14:56:56 -0800 Subject: [INET_DIAG]: Introduce sk_diag_fill To be called from inet_diag_get_exact, also rename inet_diag_fill to inet_csk_diag_fill, for consistency with inet_twsk_diag_fill. Signed-off-by: Arnaldo Carvalho de Melo Signed-off-by: David S. Miller --- net/ipv4/inet_diag.c | 34 ++++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c index 985c573..457db99 100644 --- a/net/ipv4/inet_diag.c +++ b/net/ipv4/inet_diag.c @@ -50,9 +50,10 @@ static struct sock *idiagnl; #define INET_DIAG_PUT(skb, attrtype, attrlen) \ RTA_DATA(__RTA_PUT(skb, attrtype, attrlen)) -static int inet_diag_fill(struct sk_buff *skb, struct sock *sk, - int ext, u32 pid, u32 seq, u16 nlmsg_flags, - const struct nlmsghdr *unlh) +static int inet_csk_diag_fill(struct sock *sk, + struct sk_buff *skb, + int ext, u32 pid, u32 seq, u16 nlmsg_flags, + const struct nlmsghdr *unlh) { const struct inet_sock *inet = inet_sk(sk); const struct inet_connection_sock *icsk = inet_csk(sk); @@ -212,6 +213,17 @@ nlmsg_failure: return -1; } +static int sk_diag_fill(struct sock *sk, struct sk_buff *skb, + int ext, u32 pid, u32 seq, u16 nlmsg_flags, + const struct nlmsghdr *unlh) +{ + if (sk->sk_state == TCP_TIME_WAIT) + return inet_twsk_diag_fill((struct inet_timewait_sock *)sk, + skb, ext, pid, seq, nlmsg_flags, + unlh); + return inet_csk_diag_fill(sk, skb, ext, pid, seq, nlmsg_flags, unlh); +} + static int inet_diag_get_exact(struct sk_buff *in_skb, const struct nlmsghdr *nlh) { @@ -263,7 +275,7 @@ static int inet_diag_get_exact(struct sk_buff *in_skb, if (!rep) goto out; - if (inet_diag_fill(rep, sk, req->idiag_ext, + if (sk_diag_fill(sk, rep, req->idiag_ext, NETLINK_CB(in_skb).pid, nlh->nlmsg_seq, 0, nlh) <= 0) BUG(); @@ -442,8 +454,9 @@ static int inet_diag_bc_audit(const void *bytecode, int bytecode_len) return len == 0 ? 0 : -EINVAL; } -static int inet_diag_dump_sock(struct sk_buff *skb, struct sock *sk, - struct netlink_callback *cb) +static int inet_csk_diag_dump(struct sock *sk, + struct sk_buff *skb, + struct netlink_callback *cb) { struct inet_diag_req *r = NLMSG_DATA(cb->nlh); @@ -473,8 +486,9 @@ static int inet_diag_dump_sock(struct sk_buff *skb, struct sock *sk, return 0; } - return inet_diag_fill(skb, sk, r->idiag_ext, NETLINK_CB(cb->skb).pid, - cb->nlh->nlmsg_seq, NLM_F_MULTI, cb->nlh); + return inet_csk_diag_fill(sk, skb, r->idiag_ext, + NETLINK_CB(cb->skb).pid, + cb->nlh->nlmsg_seq, NLM_F_MULTI, cb->nlh); } static int inet_twsk_diag_dump(struct inet_timewait_sock *tw, @@ -694,7 +708,7 @@ static int inet_diag_dump(struct sk_buff *skb, struct netlink_callback *cb) cb->args[3] > 0) goto syn_recv; - if (inet_diag_dump_sock(skb, sk, cb) < 0) { + if (inet_csk_diag_dump(sk, skb, cb) < 0) { inet_listen_unlock(hashinfo); goto done; } @@ -750,7 +764,7 @@ skip_listen_ht: if (r->id.idiag_dport != inet->dport && r->id.idiag_dport) goto next_normal; - if (inet_diag_dump_sock(skb, sk, cb) < 0) { + if (inet_csk_diag_dump(sk, skb, cb) < 0) { read_unlock_bh(&head->lock); goto done; } -- cgit v1.1