* [PATCH 3/5] ah6: convert to ahash
From: Steffen Klassert @ 2009-10-08 8:49 UTC (permalink / raw)
To: David Miller, Herbert Xu; +Cc: netdev
In-Reply-To: <20091008084631.GJ15653@secunet.com>
This patch converts ah6 to the new ahash interface.
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
---
net/ipv6/ah6.c | 352 +++++++++++++++++++++++++++++++++++++++++++-------------
1 files changed, 272 insertions(+), 80 deletions(-)
diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c
index c1589e2..0f526f8 100644
--- a/net/ipv6/ah6.c
+++ b/net/ipv6/ah6.c
@@ -24,18 +24,92 @@
* This file is derived from net/ipv4/ah.c.
*/
+#include <crypto/hash.h>
#include <linux/module.h>
#include <net/ip.h>
#include <net/ah.h>
#include <linux/crypto.h>
#include <linux/pfkeyv2.h>
-#include <linux/spinlock.h>
#include <linux/string.h>
+#include <linux/scatterlist.h>
#include <net/icmp.h>
#include <net/ipv6.h>
#include <net/protocol.h>
#include <net/xfrm.h>
+#define IPV6HDR_BASELEN 8
+
+struct tmp_ext {
+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
+ struct in6_addr saddr;
+#endif
+ struct in6_addr daddr;
+ char hdrs[0];
+};
+
+struct ah_skb_cb {
+ struct xfrm_skb_cb xfrm;
+ void *tmp;
+};
+
+#define AH_SKB_CB(__skb) ((struct ah_skb_cb *)&((__skb)->cb[0]))
+
+static void *ah_alloc_tmp(struct crypto_ahash *ahash, int nfrags,
+ unsigned int size)
+{
+ unsigned int len;
+
+ len = size + crypto_ahash_digestsize(ahash) +
+ (crypto_ahash_alignmask(ahash) &
+ ~(crypto_tfm_ctx_alignment() - 1));
+
+ len = ALIGN(len, crypto_tfm_ctx_alignment());
+
+ len += sizeof(struct ahash_request) + crypto_ahash_reqsize(ahash);
+ len = ALIGN(len, __alignof__(struct scatterlist));
+
+ len += sizeof(struct scatterlist) * nfrags;
+
+ return kmalloc(len, GFP_ATOMIC);
+}
+
+static inline struct tmp_ext *ah_tmp_ext(void *base)
+{
+ return base + IPV6HDR_BASELEN;
+}
+
+static inline u8 *ah_tmp_auth(u8 *tmp, unsigned int offset)
+{
+ return tmp + offset;
+}
+
+static inline u8 *ah_tmp_icv(struct crypto_ahash *ahash, void *tmp,
+ unsigned int offset)
+{
+ return PTR_ALIGN((u8 *)tmp + offset, crypto_ahash_alignmask(ahash) + 1);
+}
+
+static inline struct ahash_request *ah_tmp_req(struct crypto_ahash *ahash,
+ u8 *icv)
+{
+ struct ahash_request *req;
+
+ req = (void *)PTR_ALIGN(icv + crypto_ahash_digestsize(ahash),
+ crypto_tfm_ctx_alignment());
+
+ ahash_request_set_tfm(req, ahash);
+
+ return req;
+}
+
+static inline struct scatterlist *ah_req_sg(struct crypto_ahash *ahash,
+ struct ahash_request *req)
+{
+ return (void *)ALIGN((unsigned long)(req + 1) +
+ crypto_ahash_reqsize(ahash),
+ __alignof__(struct scatterlist));
+}
+
static int zero_out_mutable_opts(struct ipv6_opt_hdr *opthdr)
{
u8 *opt = (u8 *)opthdr;
@@ -218,24 +292,85 @@ static int ipv6_clear_mutable_options(struct ipv6hdr *iph, int len, int dir)
return 0;
}
+static void ah6_output_done(struct crypto_async_request *base, int err)
+{
+ int extlen;
+ u8 *iph_base;
+ u8 *icv;
+ struct sk_buff *skb = base->data;
+ struct xfrm_state *x = skb_dst(skb)->xfrm;
+ struct ah_data *ahp = x->data;
+ struct ipv6hdr *top_iph = ipv6_hdr(skb);
+ struct ip_auth_hdr *ah = ip_auth_hdr(skb);
+ struct tmp_ext *iph_ext;
+
+ extlen = skb_network_header_len(skb) - sizeof(struct ipv6hdr);
+ if (extlen)
+ extlen += sizeof(*iph_ext);
+
+ iph_base = AH_SKB_CB(skb)->tmp;
+ iph_ext = ah_tmp_ext(iph_base);
+ icv = ah_tmp_icv(ahp->ahash, iph_ext, extlen);
+
+ memcpy(ah->auth_data, icv, ahp->icv_trunc_len);
+ memcpy(top_iph, iph_base, IPV6HDR_BASELEN);
+
+ if (extlen) {
+#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
+ memcpy(&top_iph->saddr, iph_ext, extlen);
+#else
+ memcpy(&top_iph->daddr, iph_ext, extlen);
+#endif
+ }
+
+ err = ah->nexthdr;
+
+ kfree(AH_SKB_CB(skb)->tmp);
+ xfrm_output_resume(skb, err);
+}
+
static int ah6_output(struct xfrm_state *x, struct sk_buff *skb)
{
int err;
+ int nfrags;
int extlen;
+ u8 *iph_base;
+ u8 *icv;
+ u8 nexthdr;
+ struct sk_buff *trailer;
+ struct crypto_ahash *ahash;
+ struct ahash_request *req;
+ struct scatterlist *sg;
struct ipv6hdr *top_iph;
struct ip_auth_hdr *ah;
struct ah_data *ahp;
- u8 nexthdr;
- char tmp_base[8];
- struct {
-#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
- struct in6_addr saddr;
-#endif
- struct in6_addr daddr;
- char hdrs[0];
- } *tmp_ext;
+ struct tmp_ext *iph_ext;
+
+ ahp = x->data;
+ ahash = ahp->ahash;
+
+ if ((err = skb_cow_data(skb, 0, &trailer)) < 0)
+ goto out;
+ nfrags = err;
skb_push(skb, -skb_network_offset(skb));
+ extlen = skb_network_header_len(skb) - sizeof(struct ipv6hdr);
+ if (extlen)
+ extlen += sizeof(*iph_ext);
+
+ err = -ENOMEM;
+ iph_base = ah_alloc_tmp(ahash, nfrags, IPV6HDR_BASELEN + extlen);
+ if (!iph_base)
+ goto out;
+
+ iph_ext = ah_tmp_ext(iph_base);
+ icv = ah_tmp_icv(ahash, iph_ext, extlen);
+ req = ah_tmp_req(ahash, icv);
+ sg = ah_req_sg(ahash, req);
+
+ ah = ip_auth_hdr(skb);
+ memset(ah->auth_data, 0, ahp->icv_trunc_len);
+
top_iph = ipv6_hdr(skb);
top_iph->payload_len = htons(skb->len - sizeof(*top_iph));
@@ -245,31 +380,22 @@ static int ah6_output(struct xfrm_state *x, struct sk_buff *skb)
/* When there are no extension headers, we only need to save the first
* 8 bytes of the base IP header.
*/
- memcpy(tmp_base, top_iph, sizeof(tmp_base));
+ memcpy(iph_base, top_iph, IPV6HDR_BASELEN);
- tmp_ext = NULL;
- extlen = skb_transport_offset(skb) - sizeof(struct ipv6hdr);
if (extlen) {
- extlen += sizeof(*tmp_ext);
- tmp_ext = kmalloc(extlen, GFP_ATOMIC);
- if (!tmp_ext) {
- err = -ENOMEM;
- goto error;
- }
#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
- memcpy(tmp_ext, &top_iph->saddr, extlen);
+ memcpy(iph_ext, &top_iph->saddr, extlen);
#else
- memcpy(tmp_ext, &top_iph->daddr, extlen);
+ memcpy(iph_ext, &top_iph->daddr, extlen);
#endif
err = ipv6_clear_mutable_options(top_iph,
- extlen - sizeof(*tmp_ext) +
+ extlen - sizeof(*iph_ext) +
sizeof(*top_iph),
XFRM_POLICY_OUT);
if (err)
- goto error_free_iph;
+ goto out_free;
}
- ah = ip_auth_hdr(skb);
ah->nexthdr = nexthdr;
top_iph->priority = 0;
@@ -278,36 +404,80 @@ static int ah6_output(struct xfrm_state *x, struct sk_buff *skb)
top_iph->flow_lbl[2] = 0;
top_iph->hop_limit = 0;
- ahp = x->data;
ah->hdrlen = (XFRM_ALIGN8(sizeof(*ah) + ahp->icv_trunc_len) >> 2) - 2;
ah->reserved = 0;
ah->spi = x->id.spi;
ah->seq_no = htonl(XFRM_SKB_CB(skb)->seq.output);
- spin_lock_bh(&x->lock);
- err = ah_mac_digest(ahp, skb, ah->auth_data);
- memcpy(ah->auth_data, ahp->work_icv, ahp->icv_trunc_len);
- spin_unlock_bh(&x->lock);
+ sg_init_table(sg, nfrags);
+ skb_to_sgvec(skb, sg, 0, skb->len);
- if (err)
- goto error_free_iph;
+ ahash_request_set_crypt(req, sg, icv, skb->len);
+ ahash_request_set_callback(req, 0, ah6_output_done, skb);
+
+ AH_SKB_CB(skb)->tmp = iph_base;
- memcpy(top_iph, tmp_base, sizeof(tmp_base));
- if (tmp_ext) {
+ err = crypto_ahash_digest(req);
+ if (err) {
+ if (err == -EINPROGRESS)
+ goto out;
+
+ if (err == -EBUSY)
+ err = NET_XMIT_DROP;
+ goto out_free;
+ }
+
+ memcpy(ah->auth_data, icv, ahp->icv_trunc_len);
+ memcpy(top_iph, iph_base, IPV6HDR_BASELEN);
+
+ if (extlen) {
#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
- memcpy(&top_iph->saddr, tmp_ext, extlen);
+ memcpy(&top_iph->saddr, iph_ext, extlen);
#else
- memcpy(&top_iph->daddr, tmp_ext, extlen);
+ memcpy(&top_iph->daddr, iph_ext, extlen);
#endif
-error_free_iph:
- kfree(tmp_ext);
}
-error:
+out_free:
+ kfree(iph_base);
+out:
return err;
}
+static void ah6_input_done(struct crypto_async_request *base, int err)
+{
+ u8 *auth_data;
+ u8 *icv;
+ u8 *work_iph;
+ struct sk_buff *skb = base->data;
+ struct xfrm_state *x = xfrm_input_state(skb);
+ struct ah_data *ahp = x->data;
+ struct ip_auth_hdr *ah = ip_auth_hdr(skb);
+ int hdr_len = skb_network_header_len(skb);
+ int ah_hlen = (ah->hdrlen + 2) << 2;
+
+ work_iph = AH_SKB_CB(skb)->tmp;
+ auth_data = ah_tmp_auth(work_iph, hdr_len);
+ icv = ah_tmp_icv(ahp->ahash, auth_data, ahp->icv_trunc_len);
+
+ err = memcmp(icv, auth_data, ahp->icv_trunc_len) ? -EBADMSG: 0;
+ if (err)
+ goto out;
+
+ skb->network_header += ah_hlen;
+ memcpy(skb_network_header(skb), work_iph, hdr_len);
+ __skb_pull(skb, ah_hlen + hdr_len);
+ skb_set_transport_header(skb, -hdr_len);
+
+ err = ah->nexthdr;
+out:
+ kfree(AH_SKB_CB(skb)->tmp);
+ xfrm_input_resume(skb, err);
+}
+
+
+
static int ah6_input(struct xfrm_state *x, struct sk_buff *skb)
{
/*
@@ -325,14 +495,21 @@ static int ah6_input(struct xfrm_state *x, struct sk_buff *skb)
* There is offset of AH before IPv6 header after the process.
*/
+ u8 *auth_data;
+ u8 *icv;
+ u8 *work_iph;
+ struct sk_buff *trailer;
+ struct crypto_ahash *ahash;
+ struct ahash_request *req;
+ struct scatterlist *sg;
struct ip_auth_hdr *ah;
struct ipv6hdr *ip6h;
struct ah_data *ahp;
- unsigned char *tmp_hdr = NULL;
u16 hdr_len;
u16 ah_hlen;
int nexthdr;
- int err = -EINVAL;
+ int nfrags;
+ int err = -ENOMEM;
if (!pskb_may_pull(skb, sizeof(struct ip_auth_hdr)))
goto out;
@@ -345,9 +522,11 @@ static int ah6_input(struct xfrm_state *x, struct sk_buff *skb)
skb->ip_summed = CHECKSUM_NONE;
- hdr_len = skb->data - skb_network_header(skb);
+ hdr_len = skb_network_header_len(skb);
ah = (struct ip_auth_hdr *)skb->data;
ahp = x->data;
+ ahash = ahp->ahash;
+
nexthdr = ah->nexthdr;
ah_hlen = (ah->hdrlen + 2) << 2;
@@ -358,48 +537,67 @@ static int ah6_input(struct xfrm_state *x, struct sk_buff *skb)
if (!pskb_may_pull(skb, ah_hlen))
goto out;
- tmp_hdr = kmemdup(skb_network_header(skb), hdr_len, GFP_ATOMIC);
- if (!tmp_hdr)
- goto out;
ip6h = ipv6_hdr(skb);
+
+ skb_push(skb, hdr_len);
+
+ if ((err = skb_cow_data(skb, 0, &trailer)) < 0)
+ goto out;
+ nfrags = err;
+
+ work_iph = ah_alloc_tmp(ahash, nfrags, hdr_len + ahp->icv_trunc_len);
+ if (!work_iph)
+ goto out;
+
+ auth_data = ah_tmp_auth(work_iph, hdr_len);
+ icv = ah_tmp_icv(ahash, auth_data, ahp->icv_trunc_len);
+ req = ah_tmp_req(ahash, icv);
+ sg = ah_req_sg(ahash, req);
+
+ memcpy(work_iph, ip6h, hdr_len);
+ memcpy(auth_data, ah->auth_data, ahp->icv_trunc_len);
+ memset(ah->auth_data, 0, ahp->icv_trunc_len);
+
if (ipv6_clear_mutable_options(ip6h, hdr_len, XFRM_POLICY_IN))
- goto free_out;
+ goto out_free;
+
ip6h->priority = 0;
ip6h->flow_lbl[0] = 0;
ip6h->flow_lbl[1] = 0;
ip6h->flow_lbl[2] = 0;
ip6h->hop_limit = 0;
- spin_lock(&x->lock);
- {
- u8 auth_data[MAX_AH_AUTH_LEN];
+ sg_init_table(sg, nfrags);
+ skb_to_sgvec(skb, sg, 0, skb->len);
- memcpy(auth_data, ah->auth_data, ahp->icv_trunc_len);
- memset(ah->auth_data, 0, ahp->icv_trunc_len);
- skb_push(skb, hdr_len);
- err = ah_mac_digest(ahp, skb, ah->auth_data);
- if (err)
- goto unlock;
- if (memcmp(ahp->work_icv, auth_data, ahp->icv_trunc_len))
- err = -EBADMSG;
+ ahash_request_set_crypt(req, sg, icv, skb->len);
+ ahash_request_set_callback(req, 0, ah6_input_done, skb);
+
+ AH_SKB_CB(skb)->tmp = work_iph;
+
+ err = crypto_ahash_digest(req);
+ if (err) {
+ if (err == -EINPROGRESS)
+ goto out;
+
+ if (err == -EBUSY)
+ err = NET_XMIT_DROP;
+ goto out_free;
}
-unlock:
- spin_unlock(&x->lock);
+ err = memcmp(icv, auth_data, ahp->icv_trunc_len) ? -EBADMSG: 0;
if (err)
- goto free_out;
+ goto out_free;
skb->network_header += ah_hlen;
- memcpy(skb_network_header(skb), tmp_hdr, hdr_len);
+ memcpy(skb_network_header(skb), work_iph, hdr_len);
skb->transport_header = skb->network_header;
__skb_pull(skb, ah_hlen + hdr_len);
- kfree(tmp_hdr);
+ err = nexthdr;
- return nexthdr;
-
-free_out:
- kfree(tmp_hdr);
+out_free:
+ kfree(work_iph);
out:
return err;
}
@@ -430,7 +628,7 @@ static int ah6_init_state(struct xfrm_state *x)
{
struct ah_data *ahp = NULL;
struct xfrm_algo_desc *aalg_desc;
- struct crypto_hash *tfm;
+ struct crypto_ahash *ahash;
if (!x->aalg)
goto error;
@@ -442,12 +640,12 @@ static int ah6_init_state(struct xfrm_state *x)
if (ahp == NULL)
return -ENOMEM;
- tfm = crypto_alloc_hash(x->aalg->alg_name, 0, CRYPTO_ALG_ASYNC);
- if (IS_ERR(tfm))
+ ahash = crypto_alloc_ahash(x->aalg->alg_name, 0, 0);
+ if (IS_ERR(ahash))
goto error;
- ahp->tfm = tfm;
- if (crypto_hash_setkey(tfm, x->aalg->alg_key,
+ ahp->ahash = ahash;
+ if (crypto_ahash_setkey(ahash, x->aalg->alg_key,
(x->aalg->alg_key_len + 7) / 8))
goto error;
@@ -461,9 +659,9 @@ static int ah6_init_state(struct xfrm_state *x)
BUG_ON(!aalg_desc);
if (aalg_desc->uinfo.auth.icv_fullbits/8 !=
- crypto_hash_digestsize(tfm)) {
+ crypto_ahash_digestsize(ahash)) {
printk(KERN_INFO "AH: %s digestsize %u != %hu\n",
- x->aalg->alg_name, crypto_hash_digestsize(tfm),
+ x->aalg->alg_name, crypto_ahash_digestsize(ahash),
aalg_desc->uinfo.auth.icv_fullbits/8);
goto error;
}
@@ -473,10 +671,6 @@ static int ah6_init_state(struct xfrm_state *x)
BUG_ON(ahp->icv_trunc_len > MAX_AH_AUTH_LEN);
- ahp->work_icv = kmalloc(ahp->icv_full_len, GFP_KERNEL);
- if (!ahp->work_icv)
- goto error;
-
x->props.header_len = XFRM_ALIGN8(sizeof(struct ip_auth_hdr) +
ahp->icv_trunc_len);
switch (x->props.mode) {
@@ -495,8 +689,7 @@ static int ah6_init_state(struct xfrm_state *x)
error:
if (ahp) {
- kfree(ahp->work_icv);
- crypto_free_hash(ahp->tfm);
+ crypto_free_ahash(ahp->ahash);
kfree(ahp);
}
return -EINVAL;
@@ -509,8 +702,7 @@ static void ah6_destroy(struct xfrm_state *x)
if (!ahp)
return;
- kfree(ahp->work_icv);
- crypto_free_hash(ahp->tfm);
+ crypto_free_ahash(ahp->ahash);
kfree(ahp);
}
--
1.5.4.2
^ permalink raw reply related
* [PATCH 4/5] ah: Remove obsolete code
From: Steffen Klassert @ 2009-10-08 8:49 UTC (permalink / raw)
To: David Miller, Herbert Xu; +Cc: netdev
In-Reply-To: <20091008084631.GJ15653@secunet.com>
ah4 and ah6 are converted to ahash now, so we can remove the
code for the obsolete hash algorithm.
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
---
include/net/ah.h | 29 +++--------------------------
1 files changed, 3 insertions(+), 26 deletions(-)
diff --git a/include/net/ah.h b/include/net/ah.h
index 7ac5221..7573a71 100644
--- a/include/net/ah.h
+++ b/include/net/ah.h
@@ -1,44 +1,21 @@
#ifndef _NET_AH_H
#define _NET_AH_H
-#include <linux/crypto.h>
-#include <net/xfrm.h>
+#include <linux/skbuff.h>
/* This is the maximum truncated ICV length that we know of. */
#define MAX_AH_AUTH_LEN 12
+struct crypto_ahash;
+
struct ah_data
{
- u8 *work_icv;
int icv_full_len;
int icv_trunc_len;
- struct crypto_hash *tfm;
struct crypto_ahash *ahash;
};
-static inline int ah_mac_digest(struct ah_data *ahp, struct sk_buff *skb,
- u8 *auth_data)
-{
- struct hash_desc desc;
- int err;
-
- desc.tfm = ahp->tfm;
- desc.flags = 0;
-
- memset(auth_data, 0, ahp->icv_trunc_len);
- err = crypto_hash_init(&desc);
- if (unlikely(err))
- goto out;
- err = skb_icv_walk(skb, &desc, 0, skb->len, crypto_hash_update);
- if (unlikely(err))
- goto out;
- err = crypto_hash_final(&desc, ahp->work_icv);
-
-out:
- return err;
-}
-
struct ip_auth_hdr;
static inline struct ip_auth_hdr *ip_auth_hdr(const struct sk_buff *skb)
--
1.5.4.2
^ permalink raw reply related
* [PATCH 5/5] xfrm: remove skb_icv_walk
From: Steffen Klassert @ 2009-10-08 8:50 UTC (permalink / raw)
To: David Miller, Herbert Xu; +Cc: netdev
In-Reply-To: <20091008084631.GJ15653@secunet.com>
The last users of skb_icv_walk are converted to ahash now,
so skb_icv_walk is unused and can be removed.
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
---
include/net/xfrm.h | 3 --
net/xfrm/xfrm_algo.c | 78 --------------------------------------------------
2 files changed, 0 insertions(+), 81 deletions(-)
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 223e90a..d9c6dbb 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -1500,9 +1500,6 @@ struct scatterlist;
typedef int (icv_update_fn_t)(struct hash_desc *, struct scatterlist *,
unsigned int);
-extern int skb_icv_walk(const struct sk_buff *skb, struct hash_desc *tfm,
- int offset, int len, icv_update_fn_t icv_update);
-
static inline int xfrm_addr_cmp(xfrm_address_t *a, xfrm_address_t *b,
int family)
{
diff --git a/net/xfrm/xfrm_algo.c b/net/xfrm/xfrm_algo.c
index faf54c6..b393410 100644
--- a/net/xfrm/xfrm_algo.c
+++ b/net/xfrm/xfrm_algo.c
@@ -689,84 +689,6 @@ int xfrm_count_enc_supported(void)
}
EXPORT_SYMBOL_GPL(xfrm_count_enc_supported);
-/* Move to common area: it is shared with AH. */
-
-int skb_icv_walk(const struct sk_buff *skb, struct hash_desc *desc,
- int offset, int len, icv_update_fn_t icv_update)
-{
- int start = skb_headlen(skb);
- int i, copy = start - offset;
- struct sk_buff *frag_iter;
- struct scatterlist sg;
- int err;
-
- /* Checksum header. */
- if (copy > 0) {
- if (copy > len)
- copy = len;
-
- sg_init_one(&sg, skb->data + offset, copy);
-
- err = icv_update(desc, &sg, copy);
- if (unlikely(err))
- return err;
-
- if ((len -= copy) == 0)
- return 0;
- offset += copy;
- }
-
- for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
- int end;
-
- WARN_ON(start > offset + len);
-
- end = start + skb_shinfo(skb)->frags[i].size;
- if ((copy = end - offset) > 0) {
- skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
-
- if (copy > len)
- copy = len;
-
- sg_init_table(&sg, 1);
- sg_set_page(&sg, frag->page, copy,
- frag->page_offset + offset-start);
-
- err = icv_update(desc, &sg, copy);
- if (unlikely(err))
- return err;
-
- if (!(len -= copy))
- return 0;
- offset += copy;
- }
- start = end;
- }
-
- skb_walk_frags(skb, frag_iter) {
- int end;
-
- WARN_ON(start > offset + len);
-
- end = start + frag_iter->len;
- if ((copy = end - offset) > 0) {
- if (copy > len)
- copy = len;
- err = skb_icv_walk(frag_iter, desc, offset-start,
- copy, icv_update);
- if (unlikely(err))
- return err;
- if ((len -= copy) == 0)
- return 0;
- offset += copy;
- }
- start = end;
- }
- BUG_ON(len);
- return 0;
-}
-EXPORT_SYMBOL_GPL(skb_icv_walk);
-
#if defined(CONFIG_INET_ESP) || defined(CONFIG_INET_ESP_MODULE) || defined(CONFIG_INET6_ESP) || defined(CONFIG_INET6_ESP_MODULE)
void *pskb_put(struct sk_buff *skb, struct sk_buff *tail, int len)
--
1.5.4.2
^ permalink raw reply related
* Re: Nested function in drivers/of/of_mdio.c
From: Jérôme Pouiller @ 2009-10-08 8:45 UTC (permalink / raw)
To: linuxppc-dev, Grant Likely; +Cc: netdev, Andy Fleming, David S. Miller
In-Reply-To: <f608b67d0910070923h54c30c2doae08550b0791ed1b@mail.gmail.com>
I did some grep on codebase. I have not found any other instances of
nested functions, but my regexps are not enough to be 100% sure.
On Wednesday 07 October 2009 18:23:04 vb@vsbe.com wrote:
> Guys, are there other instances of nested C functions in the codebase
> or was this the first attempt?
>
> On Wed, Oct 7, 2009 at 9:11 AM, Grant Likely
<grant.likely@secretlab.ca> wrote:
> > On Wed, Oct 7, 2009 at 9:15 AM, Jérôme Pouiller <jezz@sysmic.org>
wrote:
> >> Dear,
> >>
> >> I have a problem with commit
> >> 8bc487d150b939e69830c39322df4ee486efe381 in file
> >> drivers/of/of_mdio.c in function of_phy_find_device.
> >>
> >> As you see, this function define match() as a nested function. My
> >> compiler (powerpc-e500-linux-gnu-gcc-3.4.1) raise an error during
> >> link due to this nested definition:
> >> drivers/built-in.o(.text+0x5e2a4): In function
> >> `of_phy_find_device':
> >> /home/jezz/linux-next/drivers/of/of_mdio.c:107: undefined
> >> reference to `__trampoline_setup'
> >>
> >> I am sure I could solve problem by rebuilding my toolchain.
> >> Nevertheless, I think nested function definition is not perfectly
> >> supported by all compilers. Also, I suggest to place function
> >> match() outside of scope of of_phy_find_device as in following
> >> patch.
> >
> > I'm okay with that, but if you're moving code out of the file
> > scope, then please rename the function to of_phy_match() to avoid
> > global namespace conflicts.
> >
> > g.
> >
> >> diff --git a/drivers/of/of_mdio.c b/drivers/of/of_mdio.c
> >> index bacaa53..c7b2e26 100644
> >> --- a/drivers/of/of_mdio.c
> >> +++ b/drivers/of/of_mdio.c
> >> @@ -97,6 +97,10 @@ int of_mdiobus_register(struct mii_bus *mdio,
> >> struct device_node *np) }
> >> EXPORT_SYMBOL(of_mdiobus_register);
> >>
> >> +static int match(struct device *dev, void *phy_np)
> >> +{
> >> + return dev_archdata_get_node(&dev->archdata) == phy_np;
> >> +}
> >> /**
> >> * of_phy_find_device - Give a PHY node, find the phy_device
> >> * @phy_np: Pointer to the phy's device tree node
> >> @@ -106,11 +110,6 @@ EXPORT_SYMBOL(of_mdiobus_register);
> >> struct phy_device *of_phy_find_device(struct device_node *phy_np)
> >> {
> >> struct device *d;
> >> - int match(struct device *dev, void *phy_np)
> >> - {
> >> - return dev_archdata_get_node(&dev->archdata) ==
> >> phy_np; - }
> >> -
> >> if (!phy_np)
> >> return NULL;
> >>
> >>
> >> What do you think about it?
> >>
> >> Best regards,
> >>
> >> --
> >> Jérôme Pouiller (jezz AT sysmic DOT org)
> >
> > --
> > Grant Likely, B.Sc., P.Eng.
> > Secret Lab Technologies Ltd.
> > _______________________________________________
> > Linuxppc-dev mailing list
> > Linuxppc-dev@lists.ozlabs.org
> > https://lists.ozlabs.org/listinfo/linuxppc-dev
>
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/linuxppc-dev
>
--
Jérôme Pouiller (jerome AT sysmic DOT org)
Expert Linux Embarqué
^ permalink raw reply
* Re: [RFC] multiqueue changes
From: Jarek Poplawski @ 2009-10-08 9:03 UTC (permalink / raw)
To: Eric Dumazet; +Cc: David S. Miller, Patrick McHardy, Linux Netdev List
In-Reply-To: <4ACD9255.4020008@gmail.com>
On Thu, Oct 08, 2009 at 09:18:45AM +0200, Eric Dumazet wrote:
> Say I have such non multiqueue device :
>
> 03:00.0 Ethernet controller: Broadcom Corporation NetXtreme II BCM5708S Gigabit Ethernet (rev 12)
>
> Driver bnx2
>
> This drivers does an alloc_etherdev_mq(sizeof(*bp), TX_MAX_RINGS),
> regardless of real capabilities of the NIC.
>
> Then, a bit later it does :
>
> bp->dev->real_num_tx_queues = bp->num_tx_rings;
>
> (one in my non multiqueue case)
>
> Now I have :
>
> # tc -s -d qdisc show dev eth0
> qdisc mq 0: root
> Sent 117693091 bytes 1542188 pkt (dropped 0, overlimits 0 requeues 0)
> backlog 0b 0p requeues 0
> # tc -s -d class show dev eth0
> class mq :1 root
> Sent 113935509 bytes 1492598 pkt (dropped 0, overlimits 0 requeues 0)
> backlog 0b 0p requeues 0
> class mq :2 root
> Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0)
> backlog 0b 0p requeues 0
> class mq :3 root
> Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0)
> backlog 0b 0p requeues 0
> class mq :4 root
> Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0)
> backlog 0b 0p requeues 0
> class mq :5 root
> Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0)
> backlog 0b 0p requeues 0
> class mq :6 root
> Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0)
> backlog 0b 0p requeues 0
> class mq :7 root
> Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0)
> backlog 0b 0p requeues 0
> class mq :8 root
> Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0)
> backlog 0b 0p requeues 0
>
> While in previous kernels I had :
>
> # tc -s -d qdisc show dev eth0
> qdisc pfifo_fast 0: root bands 3 priomap 1 2 2 2 1 2 0 0 1 1 1 1 1 1 1 1
> Sent 26292963818 bytes 347139141 pkts (dropped 0, overlimits 0 requeues 0)
> # tc -s -d class show dev eth0
>
>
> So I lost the default pfifo_fast classification.
IMHO it (pfifo_fast qdiscs under mq root) could/should get back.
>
> Just wondering if it could hurt some people.
>
> Anyway, should we change bnx2/tg3 drivers so that single queue devices
> have same default qdisc/class than before ?
>
> eg :
>
> diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
> index 08cddb6..7cac205 100644
> --- a/drivers/net/bnx2.c
> +++ b/drivers/net/bnx2.c
> @@ -6152,6 +6152,7 @@ bnx2_setup_int_mode(struct bnx2 *bp, int dis_msi)
>
> bp->num_tx_rings = rounddown_pow_of_two(bp->irq_nvecs);
> bp->dev->real_num_tx_queues = bp->num_tx_rings;
> + bp->dev->num_tx_queues = bp->dev->real_num_tx_queues;
>
> bp->num_rx_rings = bp->irq_nvecs;
> }
It doesn't look consistent to me wrt. the comment in netdevice.h on
num_tx_queues. But it seems we should rather use more often
real_num_tx_queue in schedulers code like dumps and maybe more
(like e.g. sch_multiq does).
Jarek P.
^ permalink raw reply
* Re: IP header identification field is zero, why?
From: thomas yang @ 2009-10-08 9:08 UTC (permalink / raw)
To: Eric Dumazet; +Cc: netdev
In-Reply-To: <4ACCABE0.2070804@gmail.com>
> ping sends "echo request" datagrams with DF set (Dont Fragment),
> and ID=0, this is a user program building a packet from scratch.
>
> When linux replies with a "echo reply", DF is not set and an ID is included
> in the answer, increasing at each packet.
>
> About your UDP tests, DF is automatically set, and
> I believe ID on DF frames is generated only for connected sockets.
>
The IP ID for TCP is non-zero, but for UDP is zero, strange.
I want to make the IP ID (not always zero) for UDP packets, what should I do?
(I want to use 'IP header ID, flags, offset, protocol' to identify an
IP packets)
^ permalink raw reply
* Re: [PATCH] Remove nested function
From: David Miller @ 2009-10-08 9:10 UTC (permalink / raw)
To: jezz; +Cc: netdev, linuxppc-dev, afleming
In-Reply-To: <1254990863-15271-1-git-send-email-jezz@sysmic.org>
From: Jérôme Pouiller <jezz@sysmic.org>
Date: Thu, 8 Oct 2009 10:34:23 +0200
> Some toolchains dislike nested function definition, so we define function match
> outside of of_phy_find_device.
>
> Signed-off-by: Jérôme Pouiller <jezz@sysmic.org>
Acked-by: David S. Miller <davem@davemloft.net>
^ permalink raw reply
* Re: IP header identification field is zero, why?
From: Eric Dumazet @ 2009-10-08 9:18 UTC (permalink / raw)
To: thomas yang; +Cc: netdev
In-Reply-To: <f4f837ab0910080208g143ceb1dj538680ff62e6bb37@mail.gmail.com>
thomas yang a écrit :
> The IP ID for TCP is non-zero, but for UDP is zero, strange.
>
> I want to make the IP ID (not always zero) for UDP packets, what should I do?
> (I want to use 'IP header ID, flags, offset, protocol' to identify an
> IP packets)
As I said, you can connect() your udp socket, if you send/receive trafic to/from a given destination.
if (connected_sock)
res = connect(sock, (struct sockaddr *)&addr, sizeof(addr));
(Only once)
Then, your sendto() can be faster (because no route lookup is performed)
if (sendto(sock, buffer, psize, 0,
connected_socks ? NULL : (struct sockaddr *)&addr,
sizeof(struct sockaddr_in)) != -1)
Then linux *will* generate an ID for each datagram.
^ permalink raw reply
* Re: r8169 ethernet hangs after a pm-suspend (and resume)
From: Alex Bennee @ 2009-10-08 9:27 UTC (permalink / raw)
To: Francois Romieu; +Cc: lkml, netdev
In-Reply-To: <20090909092822.GA18355@electric-eye.fr.zoreil.com>
2009/9/9 Francois Romieu <romieu@fr.zoreil.com>:
> Alex Bennee <kernel-hacker@bennee.com> :
> [...]
>> I've just recently gotten suspend working on my system. Unfortunately
>> after the resume event I loose access to the network.
>> As far as the system is concerned the network is configured properly
>> but every attempt to ping local nodes fails with "Host not reachable".
>
> Can the problem be described as "gigabit link setting does not survive
> suspend/resume" ?
Even further experimentation shows that ethernet functionality can
survive the resume for a few minutes before reseting. Once it gets
into this state even rmmod/modprobing the r8169 driver won't unwedge
the driver.
The symptoms are either the driver detecting an unknown MAC or setting
the physical address to 0xfffffffff which is obviously broken. I
suspect the hardware has gotten itself wedged somehow.
Is there any way to hard reset the chipset (without power cycling the
system)?
--
Alex, homepage: http://www.bennee.com/~alex/
http://www.half-llama.co.uk
^ permalink raw reply
* Re: [7/8,RFC] CAIF Protocol Stack
From: Stefano Babic @ 2009-10-08 9:48 UTC (permalink / raw)
To: Sjur Brændeland; +Cc: netdev, Kim Lilliestierna XX
In-Reply-To: <61D8D34BB13CFE408D154529C120E07902ED671E@eseldmw101.eemea.ericsson.se>
Sjur Brændeland wrote:
> Yes, I'll fix this documentation in a new PATCH delivery (hopefully) this week.
Ok, I will test it again when you will send to the ML.
> Hmm, the hanging might be due to a tight loop in the phyif_ser.c:ser_phy_tx function.
Agree. I can trace what happens and I can check that the tty write
function returns always 0. However, I can check that the ops field of
pser_tty is correctly set to the uart_* functions in serial_core.c and
that pser_tty->index points to the serial I chose. At least the
connection to the physical interface seems right.
> [snip]
> do {
> tty_wr =
> pser_tty->ops->write(pser_tty, bufp, actual_len);
Yes, tty_wr is always 0.
> If pser_tty->ops->write() returns zero it will loop infinetly.
> I guess the proper solution would be not to loop, but to implement a write_wakeup function for the tty...?
Agree, but this is not the problem now, because pser_tty->ops->write
returns always 0.
I have supposed that "clocal" was not set on the serial, but I have
found something different.
In phyif_ser.c, I traced the result of the extract function:
[snip]
do {
char *bufp;
/* By default we assume that we will extract
* all data in one go. */
cont = false;
/* Extract data from the packet. */
f.cfpkt_extract(cfpkt, sbuf_wr, WRITE_BUF_SIZE,
&actual_len);
I can state that actual_len is always wrong (at least, the first time
.ser_phy_txis called). I get a completely wrong value for it, as if this
variable is not initialized:
actual_len -1090496676
Then the uart_write function cannot work with negative numbers and
explains why it returns 0. So it seems to me at the moment there is a
bug in the extract function. What do you think about ?
Best regards,
Stefano Babic
--
stefano <stefano.babic@babic.homelinux.org>
GPG Key: 0x55814DDE
Fingerprint 4E85 2A66 4CBA 497A 2A7B D3BF 5973 F216 5581 4DDE
^ permalink raw reply
* Re: Nested function in drivers/of/of_mdio.c
From: Gabriel Paubert @ 2009-10-08 11:14 UTC (permalink / raw)
To: Jérôme Pouiller
Cc: netdev, linuxppc-dev, Andy Fleming, David S. Miller
In-Reply-To: <200910081045.12590.j.pouiller@sysmic.fr>
On Thu, Oct 08, 2009 at 10:45:12AM +0200, Jérôme Pouiller wrote:
> I did some grep on codebase. I have not found any other instances of
> nested functions, but my regexps are not enough to be 100% sure.
>From Documentation/CodingStyle, written by the Head Penguin himself:
"Heretic people all over the world have claimed that this inconsistency
is ... well ... inconsistent, but all right-thinking people know that
(a) K&R are _right_ and (b) K&R are right. Besides, functions are
special anyway (you can't nest them in C)."
^^^^^^^^^^^^^^^^^^^^^^^^
I interpret it as a clear prohibition of using nested functions
in the kernel.
Regards,
Gabriel
^ permalink raw reply
* Re: [RFC] multiqueue changes
From: Jarek Poplawski @ 2009-10-08 12:00 UTC (permalink / raw)
To: Eric Dumazet; +Cc: David S. Miller, Patrick McHardy, Linux Netdev List
In-Reply-To: <20091008090344.GA7409@ff.dom.local>
On Thu, Oct 08, 2009 at 09:03:44AM +0000, Jarek Poplawski wrote:
...
> num_tx_queues. But it seems we should rather use more often
> real_num_tx_queue in schedulers code like dumps and maybe more
> (like e.g. sch_multiq does).
...i.e. probably everywhere between dev_activate and dev_deactivate
all qdisc operations could use real_num_tx_queues (including a test
like: netif_is_real_multique), unless I miss something.
Jarek P.
^ permalink raw reply
* Re: [RFC] multiqueue changes
From: Eric Dumazet @ 2009-10-08 12:13 UTC (permalink / raw)
To: Jarek Poplawski; +Cc: David S. Miller, Patrick McHardy, Linux Netdev List
In-Reply-To: <20091008120039.GA8691@ff.dom.local>
Jarek Poplawski a écrit :
> On Thu, Oct 08, 2009 at 09:03:44AM +0000, Jarek Poplawski wrote:
> ...
>> num_tx_queues. But it seems we should rather use more often
>> real_num_tx_queue in schedulers code like dumps and maybe more
>> (like e.g. sch_multiq does).
>
> ...i.e. probably everywhere between dev_activate and dev_deactivate
> all qdisc operations could use real_num_tx_queues (including a test
> like: netif_is_real_multique), unless I miss something.
I am not sure David intent was being able to dynamically adjust real_num_tx_queue
between 1 and num_tx_queue.
For low/moderate traffic, its better to use one queue, to lower IRQ activations,
and let some cpus sleep longer.
^ permalink raw reply
* [PATCH] net: Fix OF platform drivers coldplug/hotplug when compiled as modules
From: Anton Vorontsov @ 2009-10-08 12:15 UTC (permalink / raw)
To: David Miller; +Cc: linuxppc-dev, netdev
Some OF platform drivers are missing module device tables, so they won't
load automatically on boot. This patch fixes the issue by adding proper
MODULE_DEVICE_TABLE() macros to the drivers.
Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
---
drivers/net/can/sja1000/sja1000_of_platform.c | 1 +
drivers/net/fec_mpc52xx_phy.c | 1 +
drivers/net/fs_enet/fs_enet-main.c | 1 +
drivers/net/fs_enet/mii-bitbang.c | 1 +
drivers/net/fs_enet/mii-fec.c | 1 +
drivers/net/fsl_pq_mdio.c | 1 +
drivers/net/gianfar.c | 4 +---
drivers/net/ibm_newemac/core.c | 2 ++
drivers/net/phy/mdio-gpio.c | 1 +
9 files changed, 10 insertions(+), 3 deletions(-)
diff --git a/drivers/net/can/sja1000/sja1000_of_platform.c b/drivers/net/can/sja1000/sja1000_of_platform.c
index 3373560..9dd076a 100644
--- a/drivers/net/can/sja1000/sja1000_of_platform.c
+++ b/drivers/net/can/sja1000/sja1000_of_platform.c
@@ -213,6 +213,7 @@ static struct of_device_id __devinitdata sja1000_ofp_table[] = {
{.compatible = "nxp,sja1000"},
{},
};
+MODULE_DEVICE_TABLE(of, sja1000_ofp_table);
static struct of_platform_driver sja1000_ofp_driver = {
.owner = THIS_MODULE,
diff --git a/drivers/net/fec_mpc52xx_phy.c b/drivers/net/fec_mpc52xx_phy.c
index 31e6d62..ee0f3c6 100644
--- a/drivers/net/fec_mpc52xx_phy.c
+++ b/drivers/net/fec_mpc52xx_phy.c
@@ -155,6 +155,7 @@ static struct of_device_id mpc52xx_fec_mdio_match[] = {
{ .compatible = "mpc5200b-fec-phy", },
{}
};
+MODULE_DEVICE_TABLE(of, mpc52xx_fec_mdio_match);
struct of_platform_driver mpc52xx_fec_mdio_driver = {
.name = "mpc5200b-fec-phy",
diff --git a/drivers/net/fs_enet/fs_enet-main.c b/drivers/net/fs_enet/fs_enet-main.c
index 2bc2d2b..ec2f503 100644
--- a/drivers/net/fs_enet/fs_enet-main.c
+++ b/drivers/net/fs_enet/fs_enet-main.c
@@ -1110,6 +1110,7 @@ static struct of_device_id fs_enet_match[] = {
#endif
{}
};
+MODULE_DEVICE_TABLE(of, fs_enet_match);
static struct of_platform_driver fs_enet_driver = {
.name = "fs_enet",
diff --git a/drivers/net/fs_enet/mii-bitbang.c b/drivers/net/fs_enet/mii-bitbang.c
index 93b481b..24ff9f4 100644
--- a/drivers/net/fs_enet/mii-bitbang.c
+++ b/drivers/net/fs_enet/mii-bitbang.c
@@ -221,6 +221,7 @@ static struct of_device_id fs_enet_mdio_bb_match[] = {
},
{},
};
+MODULE_DEVICE_TABLE(of, fs_enet_mdio_bb_match);
static struct of_platform_driver fs_enet_bb_mdio_driver = {
.name = "fsl-bb-mdio",
diff --git a/drivers/net/fs_enet/mii-fec.c b/drivers/net/fs_enet/mii-fec.c
index a2d69c1..96eba42 100644
--- a/drivers/net/fs_enet/mii-fec.c
+++ b/drivers/net/fs_enet/mii-fec.c
@@ -219,6 +219,7 @@ static struct of_device_id fs_enet_mdio_fec_match[] = {
#endif
{},
};
+MODULE_DEVICE_TABLE(of, fs_enet_mdio_fec_match);
static struct of_platform_driver fs_enet_fec_mdio_driver = {
.name = "fsl-fec-mdio",
diff --git a/drivers/net/fsl_pq_mdio.c b/drivers/net/fsl_pq_mdio.c
index d167090..6ac4648 100644
--- a/drivers/net/fsl_pq_mdio.c
+++ b/drivers/net/fsl_pq_mdio.c
@@ -407,6 +407,7 @@ static struct of_device_id fsl_pq_mdio_match[] = {
},
{},
};
+MODULE_DEVICE_TABLE(of, fsl_pq_mdio_match);
static struct of_platform_driver fsl_pq_mdio_driver = {
.name = "fsl-pq_mdio",
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
index 1e5289f..5bf31f1 100644
--- a/drivers/net/gianfar.c
+++ b/drivers/net/gianfar.c
@@ -2325,9 +2325,6 @@ static irqreturn_t gfar_error(int irq, void *dev_id)
return IRQ_HANDLED;
}
-/* work with hotplug and coldplug */
-MODULE_ALIAS("platform:fsl-gianfar");
-
static struct of_device_id gfar_match[] =
{
{
@@ -2336,6 +2333,7 @@ static struct of_device_id gfar_match[] =
},
{},
};
+MODULE_DEVICE_TABLE(of, gfar_match);
/* Structure for a device driver */
static struct of_platform_driver gfar_driver = {
diff --git a/drivers/net/ibm_newemac/core.c b/drivers/net/ibm_newemac/core.c
index 89c82c5..4baa37c 100644
--- a/drivers/net/ibm_newemac/core.c
+++ b/drivers/net/ibm_newemac/core.c
@@ -24,6 +24,7 @@
*
*/
+#include <linux/module.h>
#include <linux/sched.h>
#include <linux/string.h>
#include <linux/errno.h>
@@ -2985,6 +2986,7 @@ static struct of_device_id emac_match[] =
},
{},
};
+MODULE_DEVICE_TABLE(of, emac_match);
static struct of_platform_driver emac_driver = {
.name = "emac",
diff --git a/drivers/net/phy/mdio-gpio.c b/drivers/net/phy/mdio-gpio.c
index 250e10f..8659d34 100644
--- a/drivers/net/phy/mdio-gpio.c
+++ b/drivers/net/phy/mdio-gpio.c
@@ -238,6 +238,7 @@ static struct of_device_id mdio_ofgpio_match[] = {
},
{},
};
+MODULE_DEVICE_TABLE(of, mdio_ofgpio_match);
static struct of_platform_driver mdio_ofgpio_driver = {
.name = "mdio-gpio",
--
1.6.3.3
^ permalink raw reply related
* Re: [RFC] multiqueue changes
From: Jarek Poplawski @ 2009-10-08 12:53 UTC (permalink / raw)
To: Eric Dumazet; +Cc: David S. Miller, Patrick McHardy, Linux Netdev List
In-Reply-To: <4ACDD762.9080101@gmail.com>
On Thu, Oct 08, 2009 at 02:13:22PM +0200, Eric Dumazet wrote:
> Jarek Poplawski a écrit :
> > On Thu, Oct 08, 2009 at 09:03:44AM +0000, Jarek Poplawski wrote:
> > ...
> >> num_tx_queues. But it seems we should rather use more often
> >> real_num_tx_queue in schedulers code like dumps and maybe more
> >> (like e.g. sch_multiq does).
> >
> > ...i.e. probably everywhere between dev_activate and dev_deactivate
> > all qdisc operations could use real_num_tx_queues (including a test
> > like: netif_is_real_multique), unless I miss something.
>
> I am not sure David intent was being able to dynamically adjust real_num_tx_queue
> between 1 and num_tx_queue.
If so, then it looks like some drivers could misuse this intent.
Thanks for the explanation,
Jarek P.
^ permalink raw reply
* [PATCH] net: Use routing mark from skb in multicast forwarding routing lookups
From: Atis Elsts @ 2009-10-08 13:19 UTC (permalink / raw)
To: David Miller; +Cc: netdev, panther, eric.dumazet, brian.haley, zenczykowski
In-Reply-To: <20091007.135627.96995518.davem@davemloft.net>
On Wednesday 07 October 2009 23:56:27 David Miller wrote:
>
> Ok submit just the else part and we'll have a look at it.
>
Here is a try.
Use routing mark from skb in routing lookup in IPv4 and IPv6 multicast forwarding code.
Signed-off-by: Atis Elsts <atis@mikrotik.com>
---
net/ipv4/ipmr.c | 1 +
net/ipv6/ip6mr.c | 1 +
2 files changed, 2 insertions(+)
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
index 630a56d..5522cf8 100644
--- a/net/ipv4/ipmr.c
+++ b/net/ipv4/ipmr.c
@@ -1248,6 +1248,7 @@ static void ipmr_queue_xmit(struct sk_buff *skb, struct mfc_cache *c, int vifi)
encap = sizeof(struct iphdr);
} else {
struct flowi fl = { .oif = vif->link,
+ .mark = skb->mark,
.nl_u = { .ip4_u =
{ .daddr = iph->daddr,
.tos = RT_TOS(iph->tos) } },
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c
index 7161539..d98df54 100644
--- a/net/ipv6/ip6mr.c
+++ b/net/ipv6/ip6mr.c
@@ -1523,6 +1523,7 @@ static int ip6mr_forward2(struct sk_buff *skb, struct mfc6_cache *c, int vifi)
fl = (struct flowi) {
.oif = vif->link,
+ .mark = skb->mark,
.nl_u = { .ip6_u =
{ .daddr = ipv6h->daddr, }
}
^ permalink raw reply related
* Re: [PATCH] Generalize socket rx gap / receive queue overflow cmsg
From: Neil Horman @ 2009-10-08 13:54 UTC (permalink / raw)
To: Eric Dumazet; +Cc: netdev, davem, socketcan
In-Reply-To: <4ACD3AC8.608@gmail.com>
>
> > + if (check_drops) {
> > + skb = skb_recv_datagram(sk, flags|MSG_PEEK,
> > + flags & MSG_DONTWAIT, &err);
>
> Ouch, this is too expensive, please find another way :)
>
> > + if (skb) {
> > + gap = skb->dropcount;
> > + consume_skb(skb);
> > + }
> > + }
> > +
I'm not sure that I see the expense here, and what expense there is, I don't see
how it avoidable. In order to do this reporting at the socket level, we need to
look at the skb at the head of the receive queue. But we need to do so in a way
thats consistent with the flags being passed in (i.e. if this is a blocking
socket, we need to block here until something is available to read). Then its
just an atomic_inc on skb->users, followed by a dec in the consume_skb. I could
implement the logic for DONTWAIT myself, and skip the atomic_inc/dec, but I'm
not sure thats much of a savings. If you have another thought, I'm certainly
open to it.
Neil
> > + rc = sock->ops->recvmsg(iocb, sock, msg, size, flags);
> > +
> > + if (check_drops && (rc > 0))
>
> && gap != 0
>
> > + put_cmsg(msg, SOL_SOCKET, SO_RXQ_OVFL, sizeof(__u32), &gap);
> > +
>
>
^ permalink raw reply
* Re: [7/8,RFC] CAIF Protocol Stack
From: Stefano Babic @ 2009-10-08 14:03 UTC (permalink / raw)
To: Sjur Brændeland; +Cc: netdev, Kim Lilliestierna XX
In-Reply-To: <61D8D34BB13CFE408D154529C120E07902ED671E@eseldmw101.eemea.ericsson.se>
Sjur Brændeland wrote:
> If pser_tty->ops->write() returns zero it will loop infinetly.
> I guess the proper solution would be not to loop, but to implement a write_wakeup function for the tty...?
I discovered there is a production bug in the Makefile and the setup of
the extract function in cfcnfg_get_packet_funcs() is inconsistent.
Indeed, I traced the address of the extract function and I can find that
the address does not point to cfpkt_extract(), as I assumed.
The problem is due to the usage of the define CAIF_USE_SKB. This is used
in caif_layer.h, but some files (net/caif/*) are compiled with the macro
defined, while the drivers (drivers/net/caif/*) not.
Rather I did not get an "oops", because a valid pointer was set....but
to the wrong function !
I have also seen that CAIF_USE_SKB is not used in
cfpkt_get_packet_funcs, and this generates a problem if CAIF_USE_SKB is
not set, because the "fromnative" and "tonative" functions are always
set, even if they do not belong to the structure.
IMHO should be possible to get rid of the usage of CAIF_USE_SKB in the
structure definition (in caif_layer.h) and to provide always the same
structure definition in both case. I would prefer to set the values of
cfpkt_fromnative and cfpkt_tonative to NULL, instead of reducing the
size of the structure.
I mean, something like this:
void cfpkt_get_packet_funcs(caif_packet_funcs_t *f)
{
#ifdef CAIF_USE_SKB
f->cfpkt_fromnative = cfpkt_fromnative;
f->cfpkt_tonative = cfpkt_tonative;
#else
f->cfpkt_fromnative = NULL;
f->cfpkt_tonative = NULL;
#endif
I am not sure I understood the meaning of using this structure, because
at the moment the setup is fixed and I cannot find any point in code
where the structure is assigned to another set of functions. Probably
you arrange to have multiple choices in future, I can suppose.
What about to pass directly the pointer to the structure instead of
copying returning its value ? It seems not necessary to me, I changed
cfpkt_get_packet_funcs in this direction.
Meanwhile, it seems some bytes are sent now to the physical interface.
<caif_chropen:797, TRACE> [caif_chropen:797] WAIT FOR CONNECT RESPONSE
<caif_chropen:820, TRACE> caif_open: connect timed out
However, I get no connection, but probably this is another problem....
Best Regards,
Stefano Babic
--
stefano <stefano.babic@babic.homelinux.org>
GPG Key: 0x55814DDE
Fingerprint 4E85 2A66 4CBA 497A 2A7B D3BF 5973 F216 5581 4DDE
^ permalink raw reply
* [PATCH -next][resubmit] cdc_ether: additional Ericsson MBM PID's to the whitelist
From: Torgny Johansson @ 2009-10-08 14:20 UTC (permalink / raw)
To: davem; +Cc: netdev
Hi!
This is a new attempt to submit a patch that adds seven more PID's to the whitelist set of device. Been having some problems submitting patches with Outlook (yes I know that is a baaad idea :)) but hopefully this will get sent right.
Devices added to the whitelist:
- Ericsson Mobile Broadband variants (F3607gw and F3307)
- Dell F3607gw variants
- Toshiba F3607gw variants
Regards
Torgny Johansson
Signed-off-by: Torgny Johansson <torgny.johansson@ericsson.com>
--
diff --git a/drivers/net/usb/Kconfig b/drivers/net/usb/Kconfig
index c47237c..32d9356 100644
--- a/drivers/net/usb/Kconfig
+++ b/drivers/net/usb/Kconfig
@@ -174,7 +174,7 @@ config USB_NET_CDCETHER
* Ericsson Mobile Broadband Module (all variants)
* Motorola (DM100 and SB4100)
* Broadcom Cable Modem (reference design)
- * Toshiba (PCX1100U and F3507g)
+ * Toshiba (PCX1100U and F3507g/F3607gw)
* ...
This driver creates an interface named "ethX", where X depends on
diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c
index 4a6aff5..5d99106 100644
--- a/drivers/net/usb/cdc_ether.c
+++ b/drivers/net/usb/cdc_ether.c
@@ -544,20 +544,55 @@ static const struct usb_device_id products [] = {
USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE),
.driver_info = (unsigned long) &cdc_info,
}, {
- /* Ericsson F3307 */
+ /* Ericsson F3607gw ver 2 */
+ USB_DEVICE_AND_INTERFACE_INFO(0x0bdb, 0x1905, USB_CLASS_COMM,
+ USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE),
+ .driver_info = (unsigned long) &cdc_info,
+}, {
+ /* Ericsson F3607gw ver 3 */
USB_DEVICE_AND_INTERFACE_INFO(0x0bdb, 0x1906, USB_CLASS_COMM,
USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE),
.driver_info = (unsigned long) &cdc_info,
}, {
+ /* Ericsson F3307 */
+ USB_DEVICE_AND_INTERFACE_INFO(0x0bdb, 0x190a, USB_CLASS_COMM,
+ USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE),
+ .driver_info = (unsigned long) &cdc_info,
+}, {
+ /* Ericsson F3307 ver 2 */
+ USB_DEVICE_AND_INTERFACE_INFO(0x0bdb, 0x1909, USB_CLASS_COMM,
+ USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE),
+ .driver_info = (unsigned long) &cdc_info,
+}, {
/* Toshiba F3507g */
USB_DEVICE_AND_INTERFACE_INFO(0x0930, 0x130b, USB_CLASS_COMM,
USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE),
.driver_info = (unsigned long) &cdc_info,
}, {
+ /* Toshiba F3607gw */
+ USB_DEVICE_AND_INTERFACE_INFO(0x0930, 0x130c, USB_CLASS_COMM,
+ USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE),
+ .driver_info = (unsigned long) &cdc_info,
+}, {
+ /* Toshiba F3607gw ver 2 */
+ USB_DEVICE_AND_INTERFACE_INFO(0x0930, 0x1311, USB_CLASS_COMM,
+ USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE),
+ .driver_info = (unsigned long) &cdc_info,
+}, {
/* Dell F3507g */
USB_DEVICE_AND_INTERFACE_INFO(0x413c, 0x8147, USB_CLASS_COMM,
USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE),
.driver_info = (unsigned long) &cdc_info,
+}, {
+ /* Dell F3607gw */
+ USB_DEVICE_AND_INTERFACE_INFO(0x413c, 0x8183, USB_CLASS_COMM,
+ USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE),
+ .driver_info = (unsigned long) &cdc_info,
+}, {
+ /* Dell F3607gw ver 2 */
+ USB_DEVICE_AND_INTERFACE_INFO(0x413c, 0x8184, USB_CLASS_COMM,
+ USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE),
+ .driver_info = (unsigned long) &cdc_info,
},
{ }, // END
};
--
^ permalink raw reply related
* Re: [PATCH] Generalize socket rx gap / receive queue overflow cmsg
From: Eric Dumazet @ 2009-10-08 14:45 UTC (permalink / raw)
To: Neil Horman; +Cc: netdev, davem, socketcan
In-Reply-To: <20091008135435.GA23928@hmsreliant.think-freely.org>
Neil Horman a écrit :
>>> + if (check_drops) {
>>> + skb = skb_recv_datagram(sk, flags|MSG_PEEK,
>>> + flags & MSG_DONTWAIT, &err);
>> Ouch, this is too expensive, please find another way :)
>>
>>> + if (skb) {
>>> + gap = skb->dropcount;
>>> + consume_skb(skb);
>>> + }
>>> + }
>>> +
> I'm not sure that I see the expense here, and what expense there is, I don't see
> how it avoidable. In order to do this reporting at the socket level, we need to
> look at the skb at the head of the receive queue. But we need to do so in a way
> thats consistent with the flags being passed in (i.e. if this is a blocking
> socket, we need to block here until something is available to read). Then its
> just an atomic_inc on skb->users, followed by a dec in the consume_skb. I could
> implement the logic for DONTWAIT myself, and skip the atomic_inc/dec, but I'm
> not sure thats much of a savings. If you have another thought, I'm certainly
> open to it.
The expense is a lot of atomic ops. You forgot the lock, so thats four atomic ops.
You can do all this with no extra atomics.
All you need is some function with (struct msghdr *msg, struct sock *sk, struct sk_buff *skb)
triplet.
hint : sock_recv_timestamp(struct msghdr *msg, struct sock *sk, struct sk_buff *skb)
Could be renamed to something else if you want...
sock_recv_ts_or_drops() or whatever
^ permalink raw reply
* Re: [PATCH 2/2] [RFC] Add c/r support for connected INET sockets
From: John Dykstra @ 2009-10-08 14:47 UTC (permalink / raw)
To: Dan Smith; +Cc: containers, netdev
In-Reply-To: <1254932945-12578-3-git-send-email-danms@us.ibm.com>
On Wed, 2009-10-07 at 09:29 -0700, Dan Smith wrote:
> This patch adds basic support for C/R of open INET sockets. I think
> that
> all the important bits of the TCP and ICSK socket structures is saved,
> but I think there is still some additional IPv6 stuff that needs to be
> handled.
I think this patch breaks code that was already in do_sock_restore():
struct sock *do_sock_restore(struct ckpt_ctx *ctx)
{
struct ckpt_hdr_socket *h;
struct socket *sock;
int ret;
h = ckpt_read_obj_type(ctx, sizeof(*h), CKPT_HDR_SOCKET);
if (IS_ERR(h))
return ERR_PTR(PTR_ERR(h));
/* silently clear flags, e.g. SOCK_NONBLOCK or SOCK_CLOEXEC */
h->sock.type &= SOCK_TYPE_MASK;
ret = sock_create(h->sock_common.family, h->sock.type, 0, &sock);
if (ret < 0)
goto err;
You're passing 0 as the protocol value to sock_create(). This
ultimately gets passed to the address family's create() function.
inet_create() (and its IPv6 companion) use that protocol value as the
key when they search for the proper inet_protosw, which in turn gets
mapped to the struct proto and passed to sk_prot_alloc().
In address families INET and AF_INET6, the struct sock is different
sizes for different protocols. This is implemented by the struct proto
specifying which cache the struct sock comes from.
So by passing in 0 all the time to sock_create(), you're getting a
struct sock that may not be the right size. Memory corruption and
madness follow.
-- John
^ permalink raw reply
* [PATCH] net: Fix struct sock bitfield annotation
From: Eric Dumazet @ 2009-10-08 15:16 UTC (permalink / raw)
To: David S. Miller; +Cc: Linux Netdev List, Vegard Nossum, Ingo Molnar
Since commit a98b65a3 (net: annotate struct sock bitfield), we lost 8 bytes
in struct sock on 64bits arches because of kmemcheck_bitfield_end(flags) misplacement.
struct good {
int begin_flags[0];
unsigned char a : 8;
unsigned char b;
unsigned short c;
int end_flags[0];
int sk_rcvbuf;
void *ptr;
};
struct bad {
int begin_flags[0];
unsigned char a : 8;
int end_flags[0];
unsigned char b;
unsigned short c;
int sk_rcvbuf;
void *ptr;
};
sizeof(struct good) = 16, sizeof(struct bad) = 24
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
---
include/net/sock.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/include/net/sock.h b/include/net/sock.h
index 1621935..ecfb831 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -229,9 +229,9 @@ struct sock {
unsigned char sk_shutdown : 2,
sk_no_check : 2,
sk_userlocks : 4;
- kmemcheck_bitfield_end(flags);
unsigned char sk_protocol;
unsigned short sk_type;
+ kmemcheck_bitfield_end(flags);
int sk_rcvbuf;
socket_lock_t sk_lock;
/*
^ permalink raw reply related
* net-2.6 build error on powerpc
From: Ron Mercer @ 2009-10-08 15:20 UTC (permalink / raw)
To: netdev; +Cc: ron.mercer, davem
I recently grabbed the latest net-2.6 kernel for a powerpc test box and
got this compile error.
CC arch/powerpc/kernel/cputable.o
CC arch/powerpc/kernel/ptrace.o
CC arch/powerpc/kernel/syscalls.o
CC arch/powerpc/kernel/irq.o
CC arch/powerpc/kernel/align.o
CC arch/powerpc/kernel/signal_32.o
CC arch/powerpc/kernel/pmc.o
CC arch/powerpc/kernel/vdso.o
cc1: warnings being treated as errors
arch/powerpc/kernel/vdso.c:78: warning: alignment of
âso_data_storeâs greater than maximum object file
alignment. Using 32768
make[1]: *** [arch/powerpc/kernel/vdso.o] Error 1
make: *** [arch/powerpc/kernel] Error 2
[root@localhost linux-2.6-net.git]#
Any suggestions would be appreciated.
^ permalink raw reply
* Re: [PATCH 2/2] [RFC] Add c/r support for connected INET sockets
From: Dan Smith @ 2009-10-08 15:41 UTC (permalink / raw)
To: John Dykstra
Cc: containers-qjLDD68F18O7TbgM5vRIOg, netdev-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1255013233.8033.14.camel@Maple>
JD> You're passing 0 as the protocol value to sock_create(). This
JD> ultimately gets passed to the address family's create() function.
The fix is to pass in the previous version of sk_protocol instead of
zero, right? It looks like inet_create() has enough intelligence to
weed out invalid values for us too...
--
Dan Smith
IBM Linux Technology Center
email: danms-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org
^ permalink raw reply
* [PATCH][v2] ibm_newemac: Added 16K Tx FIFO size support for EMAC4
From: Dave Mitchell @ 2009-10-08 16:32 UTC (permalink / raw)
To: netdev; +Cc: linuxppc-dev, Dave Mitchell
Some of the EMAC V4 implementations support 16K Tx FIFOs. This
patch adds support for this functionality and fixes typos in the
Tx FIFO size error messages.
Signed-off-by: Dave Mitchell <dmitchell@appliedmicro.com>
Acked-by: Prodyut Hazarika <phazarika@appliedmicro.com>
Acked-by: Victor Gallardo <vgallardo@appliedmicro.com>
Acked-by: Loc Ho <lho@appliedmicro.com>
---
v1->v2: local date/time was out-of-sync and thus mail was as well
drivers/net/ibm_newemac/core.c | 7 +++++--
drivers/net/ibm_newemac/emac.h | 1 +
2 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ibm_newemac/core.c b/drivers/net/ibm_newemac/core.c
index 89c82c5..c6591cb 100644
--- a/drivers/net/ibm_newemac/core.c
+++ b/drivers/net/ibm_newemac/core.c
@@ -443,7 +443,7 @@ static u32 __emac_calc_base_mr1(struct emac_instance *dev, int tx_size, int rx_s
ret |= EMAC_MR1_TFS_2K;
break;
default:
- printk(KERN_WARNING "%s: Unknown Rx FIFO size %d\n",
+ printk(KERN_WARNING "%s: Unknown Tx FIFO size %d\n",
dev->ndev->name, tx_size);
}
@@ -470,6 +470,9 @@ static u32 __emac4_calc_base_mr1(struct emac_instance *dev, int tx_size, int rx_
DBG2(dev, "__emac4_calc_base_mr1" NL);
switch(tx_size) {
+ case 16384:
+ ret |= EMAC4_MR1_TFS_16K;
+ break;
case 4096:
ret |= EMAC4_MR1_TFS_4K;
break;
@@ -477,7 +480,7 @@ static u32 __emac4_calc_base_mr1(struct emac_instance *dev, int tx_size, int rx_
ret |= EMAC4_MR1_TFS_2K;
break;
default:
- printk(KERN_WARNING "%s: Unknown Rx FIFO size %d\n",
+ printk(KERN_WARNING "%s: Unknown Tx FIFO size %d\n",
dev->ndev->name, tx_size);
}
diff --git a/drivers/net/ibm_newemac/emac.h b/drivers/net/ibm_newemac/emac.h
index 0afc2cf..d34adf9 100644
--- a/drivers/net/ibm_newemac/emac.h
+++ b/drivers/net/ibm_newemac/emac.h
@@ -153,6 +153,7 @@ struct emac_regs {
#define EMAC4_MR1_RFS_16K 0x00280000
#define EMAC4_MR1_TFS_2K 0x00020000
#define EMAC4_MR1_TFS_4K 0x00030000
+#define EMAC4_MR1_TFS_16K 0x00050000
#define EMAC4_MR1_TR 0x00008000
#define EMAC4_MR1_MWSW_001 0x00001000
#define EMAC4_MR1_JPSM 0x00000800
--
1.6.3.2
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox