Netdev List
 help / color / mirror / Atom feed
* Re: [PATCH] IPv6 support for NFS server
From: J. Bruce Fields @ 2007-12-10 18:34 UTC (permalink / raw)
  To: Aurélien Charbon; +Cc: netdev ML, Mailing list NFSv4
In-Reply-To: <475D86C1.6070400@ext.bull.net>

On Mon, Dec 10, 2007 at 07:34:41PM +0100, Aurélien Charbon wrote:
>
> Here is a cleanup for the ip_map caching patch in nfs server.
>
> It prepares for IPv6 text-based mounts and exports.
>
> Tests: tested with only IPv4 network and basic nfs ops (mount, file 
> creation and modification)

Thanks!  And also tested with an unmodified rpc.mountd?

--b.

>
> -----
>
> Signed-off-by: Aurelien Charbon <aurelien.charbon@bull.net>
>
> diff -p -u -r -N linux-2.6.24-rc4/fs/nfsd/export.c 
> linux-2.6.24-rc4-IPv6-cache-based/fs/nfsd/export.c
> --- linux-2.6.24-rc4/fs/nfsd/export.c    2007-12-10 16:11:37.000000000 +0100
> +++ linux-2.6.24-rc4-IPv6-cache-based/fs/nfsd/export.c    2007-12-10 
> 17:50:37.000000000 +0100
> @@ -35,6 +35,7 @@
> #include <linux/lockd/bind.h>
> #include <linux/sunrpc/msg_prot.h>
> #include <linux/sunrpc/gss_api.h>
> +#include <net/ipv6.h>
>
> #define NFSDDBG_FACILITY    NFSDDBG_EXPORT
>
> @@ -1556,6 +1557,7 @@ exp_addclient(struct nfsctl_client *ncp)
> {
>     struct auth_domain    *dom;
>     int            i, err;
> +    struct in6_addr addr6;
>
>     /* First, consistency check. */
>     err = -EINVAL;
> @@ -1574,9 +1576,12 @@ exp_addclient(struct nfsctl_client *ncp)
>         goto out_unlock;
>
>     /* Insert client into hashtable. */
> -    for (i = 0; i < ncp->cl_naddr; i++)
> -        auth_unix_add_addr(ncp->cl_addrlist[i], dom);
> -
> +    for (i = 0; i < ncp->cl_naddr; i++) {
> +        /* Mapping address */
> +        ipv6_addr_set(&addr6, 0, 0,
> +                htonl(0x0000FFFF), ncp->cl_addrlist[i].s_addr);
> +        auth_unix_add_addr(&addr6, dom);
> +    }
>     auth_unix_forget_old(dom);
>     auth_domain_put(dom);
>
> diff -p -u -r -N linux-2.6.24-rc4/fs/nfsd/nfsctl.c 
> linux-2.6.24-rc4-IPv6-cache-based/fs/nfsd/nfsctl.c
> --- linux-2.6.24-rc4/fs/nfsd/nfsctl.c    2007-12-10 16:11:37.000000000 +0100
> +++ linux-2.6.24-rc4-IPv6-cache-based/fs/nfsd/nfsctl.c    2007-12-10 
> 18:15:22.000000000 +0100
> @@ -37,6 +37,7 @@
> #include <linux/nfsd/syscall.h>
>
> #include <asm/uaccess.h>
> +#include <net/ipv6.h>
>
> /*
>  *    We have a single directory with 9 nodes in it.
> @@ -222,6 +223,7 @@ static ssize_t write_getfs(struct file *
>     struct auth_domain *clp;
>     int err = 0;
>     struct knfsd_fh *res;
> +    struct in6_addr in6;
>
>     if (size < sizeof(*data))
>         return -EINVAL;
> @@ -236,7 +238,13 @@ static ssize_t write_getfs(struct file *
>     res = (struct knfsd_fh*)buf;
>
>     exp_readlock();
> -    if (!(clp = auth_unix_lookup(sin->sin_addr)))
> +
> +    /* IPv6 address mapping */
> +    ipv6_addr_set(&in6, 0, 0,
> +            htonl(0x0000FFFF),
> +            (((struct sockaddr_in *)&data->gd_addr)->sin_addr.s_addr));
> +
> +    if (!(clp = auth_unix_lookup(in6)))
>         err = -EPERM;
>     else {
>         err = exp_rootfh(clp, data->gd_path, res, data->gd_maxlen);
> @@ -257,6 +265,7 @@ static ssize_t write_getfd(struct file *
>     int err = 0;
>     struct knfsd_fh fh;
>     char *res;
> +    struct in6_addr in6;
>
>     if (size < sizeof(*data))
>         return -EINVAL;
> @@ -271,7 +280,12 @@ static ssize_t write_getfd(struct file *
>     res = buf;
>     sin = (struct sockaddr_in *)&data->gd_addr;
>     exp_readlock();
> -    if (!(clp = auth_unix_lookup(sin->sin_addr)))
> +    /* IPv6 address mapping */
> +    ipv6_addr_set(&in6, 0, 0,
> +            htonl(0x0000FFFF),
> +            (((struct sockaddr_in *)&data->gd_addr)->sin_addr.s_addr));
> +
> +    if (!(clp = auth_unix_lookup(in6)))
>         err = -EPERM;
>     else {
>         err = exp_rootfh(clp, data->gd_path, &fh, NFS_FHSIZE);
> diff -p -u -r -N linux-2.6.24-rc4/include/linux/sunrpc/svcauth.h 
> linux-2.6.24-rc4-IPv6-cache-based/include/linux/sunrpc/svcauth.h
> --- linux-2.6.24-rc4/include/linux/sunrpc/svcauth.h    2007-12-10 
> 16:01:43.000000000 +0100
> +++ linux-2.6.24-rc4-IPv6-cache-based/include/linux/sunrpc/svcauth.h    
> 2007-12-10 17:09:34.000000000 +0100
> @@ -120,10 +120,10 @@ extern void    svc_auth_unregister(rpc_auth
>
> extern struct auth_domain *unix_domain_find(char *name);
> extern void auth_domain_put(struct auth_domain *item);
> -extern int auth_unix_add_addr(struct in_addr addr, struct auth_domain 
> *dom);
> +extern int auth_unix_add_addr(struct in6_addr *addr, struct auth_domain 
> *dom);
> extern struct auth_domain *auth_domain_lookup(char *name, struct 
> auth_domain *new);
> extern struct auth_domain *auth_domain_find(char *name);
> -extern struct auth_domain *auth_unix_lookup(struct in_addr addr);
> +extern struct auth_domain *auth_unix_lookup(struct in6_addr *addr);
> extern int auth_unix_forget_old(struct auth_domain *dom);
> extern void svcauth_unix_purge(void);
> extern void svcauth_unix_info_release(void *);
> diff -p -u -r -N linux-2.6.24-rc4/net/sunrpc/svcauth_unix.c 
> linux-2.6.24-rc4-IPv6-cache-based/net/sunrpc/svcauth_unix.c
> --- linux-2.6.24-rc4/net/sunrpc/svcauth_unix.c    2007-12-10 
> 16:01:46.000000000 +0100
> +++ linux-2.6.24-rc4-IPv6-cache-based/net/sunrpc/svcauth_unix.c    
> 2007-12-10 17:38:50.000000000 +0100
> @@ -11,7 +11,8 @@
> #include <linux/hash.h>
> #include <linux/string.h>
> #include <net/sock.h>
> -
> +#include <net/ipv6.h>
> +#include <linux/kernel.h>
> #define RPCDBG_FACILITY    RPCDBG_AUTH
>
>
> @@ -84,7 +85,7 @@ static void svcauth_unix_domain_release(
> struct ip_map {
>     struct cache_head    h;
>     char            m_class[8]; /* e.g. "nfsd" */
> -    struct in_addr        m_addr;
> +    struct in6_addr        m_addr;
>     struct unix_domain    *m_client;
>     int            m_add_change;
> };
> @@ -112,12 +113,19 @@ static inline int hash_ip(__be32 ip)
>     return (hash ^ (hash>>8)) & 0xff;
> }
> #endif
> +static inline int hash_ip6(struct in6_addr ip)
> +{
> +    return (hash_ip(ip.s6_addr32[0]) ^
> +        hash_ip(ip.s6_addr32[1]) ^
> +        hash_ip(ip.s6_addr32[2]) ^
> +        hash_ip(ip.s6_addr32[3]));
> +}
> static int ip_map_match(struct cache_head *corig, struct cache_head *cnew)
> {
>     struct ip_map *orig = container_of(corig, struct ip_map, h);
>     struct ip_map *new = container_of(cnew, struct ip_map, h);
>     return strcmp(orig->m_class, new->m_class) == 0
> -        && orig->m_addr.s_addr == new->m_addr.s_addr;
> +        && ipv6_addr_equal(&orig->m_addr, &new->m_addr);
> }
> static void ip_map_init(struct cache_head *cnew, struct cache_head *citem)
> {
> @@ -125,7 +133,7 @@ static void ip_map_init(struct cache_hea
>     struct ip_map *item = container_of(citem, struct ip_map, h);
>
>     strcpy(new->m_class, item->m_class);
> -    new->m_addr.s_addr = item->m_addr.s_addr;
> +    ipv6_addr_copy(&new->m_addr, &item->m_addr);
> }
> static void update(struct cache_head *cnew, struct cache_head *citem)
> {
> @@ -149,22 +157,24 @@ static void ip_map_request(struct cache_
>                   struct cache_head *h,
>                   char **bpp, int *blen)
> {
> -    char text_addr[20];
> +    char text_addr[40];
>     struct ip_map *im = container_of(h, struct ip_map, h);
> -    __be32 addr = im->m_addr.s_addr;
> -
> -    snprintf(text_addr, 20, "%u.%u.%u.%u",
> -         ntohl(addr) >> 24 & 0xff,
> -         ntohl(addr) >> 16 & 0xff,
> -         ntohl(addr) >>  8 & 0xff,
> -         ntohl(addr) >>  0 & 0xff);
>
> +    if (ipv6_addr_v4mapped(&(im->m_addr))) {
> +        snprintf(text_addr, 20, NIPQUAD_FMT,
> +                ntohl(im->m_addr.s6_addr32[3]) >> 24 & 0xff,
> +                ntohl(im->m_addr.s6_addr32[3]) >> 16 & 0xff,
> +                ntohl(im->m_addr.s6_addr32[3]) >>  8 & 0xff,
> +                ntohl(im->m_addr.s6_addr32[3]) >>  0 & 0xff);
> +    } else {
> +        snprintf(text_addr, 40, NIP6_FMT, NIP6(im->m_addr));
> +    }
>     qword_add(bpp, blen, im->m_class);
>     qword_add(bpp, blen, text_addr);
>     (*bpp)[-1] = '\n';
> }
>
> -static struct ip_map *ip_map_lookup(char *class, struct in_addr addr);
> +static struct ip_map *ip_map_lookup(char *class, struct in6_addr *addr);
> static int ip_map_update(struct ip_map *ipm, struct unix_domain *udom, 
> time_t expiry);
>
> static int ip_map_parse(struct cache_detail *cd,
> @@ -175,10 +185,10 @@ static int ip_map_parse(struct cache_det
>      * for scratch: */
>     char *buf = mesg;
>     int len;
> -    int b1,b2,b3,b4;
> +    int b1, b2, b3, b4, b5, b6, b7, b8;
>     char c;
>     char class[8];
> -    struct in_addr addr;
> +    struct in6_addr addr;
>     int err;
>
>     struct ip_map *ipmp;
> @@ -197,9 +207,26 @@ static int ip_map_parse(struct cache_det
>     len = qword_get(&mesg, buf, mlen);
>     if (len <= 0) return -EINVAL;
>
> -    if (sscanf(buf, "%u.%u.%u.%u%c", &b1, &b2, &b3, &b4, &c) != 4)
> +    if (sscanf(buf, NIPQUAD_FMT "%c", &b1, &b2, &b3, &b4, &c) == 4) {
> +        addr.s6_addr32[0] = 0;
> +        addr.s6_addr32[1] = 0;
> +        addr.s6_addr32[2] = htonl(0xffff);
> +        addr.s6_addr32[3] =
> +            htonl((((((b1<<8)|b2)<<8)|b3)<<8)|b4);
> +       } else if (sscanf(buf, NIP6_FMT "%c",
> +            &b1, &b2, &b3, &b4, &b5, &b6, &b7, &b8, &c) == 8) {
> +        addr.s6_addr16[0] = htons(b1);
> +        addr.s6_addr16[1] = htons(b2);
> +        addr.s6_addr16[2] = htons(b3);
> +        addr.s6_addr16[3] = htons(b4);
> +        addr.s6_addr16[4] = htons(b5);
> +        addr.s6_addr16[5] = htons(b6);
> +        addr.s6_addr16[6] = htons(b7);
> +        addr.s6_addr16[7] = htons(b8);
> +       } else
>         return -EINVAL;
>
> +
>     expiry = get_expiry(&mesg);
>     if (expiry ==0)
>         return -EINVAL;
> @@ -215,10 +242,7 @@ static int ip_map_parse(struct cache_det
>     } else
>         dom = NULL;
>
> -    addr.s_addr =
> -        htonl((((((b1<<8)|b2)<<8)|b3)<<8)|b4);
> -
> -    ipmp = ip_map_lookup(class,addr);
> +    ipmp = ip_map_lookup(class, &addr);
>     if (ipmp) {
>         err = ip_map_update(ipmp,
>                  container_of(dom, struct unix_domain, h),
> @@ -238,7 +262,7 @@ static int ip_map_show(struct seq_file *
>                struct cache_head *h)
> {
>     struct ip_map *im;
> -    struct in_addr addr;
> +    struct in6_addr addr;
>     char *dom = "-no-domain-";
>
>     if (h == NULL) {
> @@ -247,20 +271,24 @@ static int ip_map_show(struct seq_file *
>     }
>     im = container_of(h, struct ip_map, h);
>     /* class addr domain */
> -    addr = im->m_addr;
> +    ipv6_addr_copy(&addr, &im->m_addr);
>
>     if (test_bit(CACHE_VALID, &h->flags) &&
>         !test_bit(CACHE_NEGATIVE, &h->flags))
>         dom = im->m_client->h.name;
>
> -    seq_printf(m, "%s %d.%d.%d.%d %s\n",
> -           im->m_class,
> -           ntohl(addr.s_addr) >> 24 & 0xff,
> -           ntohl(addr.s_addr) >> 16 & 0xff,
> -           ntohl(addr.s_addr) >>  8 & 0xff,
> -           ntohl(addr.s_addr) >>  0 & 0xff,
> -           dom
> -           );
> +    if (ipv6_addr_v4mapped(&addr)) {
> +        seq_printf(m, "%s" NIPQUAD_FMT "%s\n",
> +            im->m_class,
> +            ntohl(addr.s6_addr32[3]) >> 24 & 0xff,
> +            ntohl(addr.s6_addr32[3]) >> 16 & 0xff,
> +            ntohl(addr.s6_addr32[3]) >>  8 & 0xff,
> +            ntohl(addr.s6_addr32[3]) >>  0 & 0xff,
> +            dom);
> +    } else {
> +        seq_printf(m, "%s" NIP6_FMT "%s\n",
> +            im->m_class, NIP6(addr), dom);
> +    }
>     return 0;
> }
>
> @@ -280,16 +308,16 @@ struct cache_detail ip_map_cache = {
>     .alloc        = ip_map_alloc,
> };
>
> -static struct ip_map *ip_map_lookup(char *class, struct in_addr addr)
> +static struct ip_map *ip_map_lookup(char *class, struct in6_addr *addr)
> {
>     struct ip_map ip;
>     struct cache_head *ch;
>
>     strcpy(ip.m_class, class);
> -    ip.m_addr = addr;
> +    ipv6_addr_copy(&ip.m_addr, addr);
>     ch = sunrpc_cache_lookup(&ip_map_cache, &ip.h,
>                  hash_str(class, IP_HASHBITS) ^
> -                 hash_ip(addr.s_addr));
> +                 hash_ip6(*addr));
>
>     if (ch)
>         return container_of(ch, struct ip_map, h);
> @@ -318,14 +346,14 @@ static int ip_map_update(struct ip_map *
>     ch = sunrpc_cache_update(&ip_map_cache,
>                  &ip.h, &ipm->h,
>                  hash_str(ipm->m_class, IP_HASHBITS) ^
> -                 hash_ip(ipm->m_addr.s_addr));
> +                 hash_ip6(ipm->m_addr));
>     if (!ch)
>         return -ENOMEM;
>     cache_put(ch, &ip_map_cache);
>     return 0;
> }
>
> -int auth_unix_add_addr(struct in_addr addr, struct auth_domain *dom)
> +int auth_unix_add_addr(struct in6_addr *addr, struct auth_domain *dom)
> {
>     struct unix_domain *udom;
>     struct ip_map *ipmp;
> @@ -352,7 +380,7 @@ int auth_unix_forget_old(struct auth_dom
>     return 0;
> }
>
> -struct auth_domain *auth_unix_lookup(struct in_addr addr)
> +struct auth_domain *auth_unix_lookup(struct in6_addr *addr)
> {
>     struct ip_map *ipm;
>     struct auth_domain *rv;
> @@ -641,9 +669,24 @@ static int unix_gid_find(uid_t uid, stru
> int
> svcauth_unix_set_client(struct svc_rqst *rqstp)
> {
> -    struct sockaddr_in *sin = svc_addr_in(rqstp);
> +    struct sockaddr_in *sin;
> +    struct sockaddr_in6 *sin6, sin6_storage;
>     struct ip_map *ipm;
>
> +    switch (rqstp->rq_addr.ss_family) {
> +    case AF_INET:
> +        sin = svc_addr_in(rqstp);
> +        sin6 = &sin6_storage;
> +        ipv6_addr_set(&sin6->sin6_addr, 0, 0,
> +                htonl(0x0000FFFF), sin->sin_addr.s_addr);
> +        break;
> +    case AF_INET6:
> +        sin6 = svc_addr_in6(rqstp);
> +        break;
> +    default:
> +        BUG();
> +    }
> +
>     rqstp->rq_client = NULL;
>     if (rqstp->rq_proc == 0)
>         return SVC_OK;
> @@ -651,7 +694,7 @@ svcauth_unix_set_client(struct svc_rqst
>     ipm = ip_map_cached_get(rqstp);
>     if (ipm == NULL)
>         ipm = ip_map_lookup(rqstp->rq_server->sv_program->pg_class,
> -                    sin->sin_addr);
> +                    &sin6->sin6_addr);
>
>     if (ipm == NULL)
>         return SVC_DENIED;
>
> -- 
>
> ********************************
>       Aurelien Charbon
>       Linux NFSv4 team
>           Bull SAS
>     Echirolles - France
> http://nfsv4.bullopensource.org/
> ********************************
>

> Signed-off-by: Aurelien Charbon <aurelien.charbon@bull.net>
> 
> diff -p -u -r -N linux-2.6.24-rc4/fs/nfsd/export.c linux-2.6.24-rc4-IPv6-cache-based/fs/nfsd/export.c
> --- linux-2.6.24-rc4/fs/nfsd/export.c	2007-12-10 16:11:37.000000000 +0100
> +++ linux-2.6.24-rc4-IPv6-cache-based/fs/nfsd/export.c	2007-12-10 17:50:37.000000000 +0100
> @@ -35,6 +35,7 @@
>  #include <linux/lockd/bind.h>
>  #include <linux/sunrpc/msg_prot.h>
>  #include <linux/sunrpc/gss_api.h>
> +#include <net/ipv6.h>
>  
>  #define NFSDDBG_FACILITY	NFSDDBG_EXPORT
>  
> @@ -1556,6 +1557,7 @@ exp_addclient(struct nfsctl_client *ncp)
>  {
>  	struct auth_domain	*dom;
>  	int			i, err;
> +	struct in6_addr addr6;
>  
>  	/* First, consistency check. */
>  	err = -EINVAL;
> @@ -1574,9 +1576,12 @@ exp_addclient(struct nfsctl_client *ncp)
>  		goto out_unlock;
>  
>  	/* Insert client into hashtable. */
> -	for (i = 0; i < ncp->cl_naddr; i++)
> -		auth_unix_add_addr(ncp->cl_addrlist[i], dom);
> -
> +	for (i = 0; i < ncp->cl_naddr; i++) {
> +		/* Mapping address */
> +		ipv6_addr_set(&addr6, 0, 0,
> +				htonl(0x0000FFFF), ncp->cl_addrlist[i].s_addr);
> +		auth_unix_add_addr(&addr6, dom);
> +	}
>  	auth_unix_forget_old(dom);
>  	auth_domain_put(dom);
>  
> diff -p -u -r -N linux-2.6.24-rc4/fs/nfsd/nfsctl.c linux-2.6.24-rc4-IPv6-cache-based/fs/nfsd/nfsctl.c
> --- linux-2.6.24-rc4/fs/nfsd/nfsctl.c	2007-12-10 16:11:37.000000000 +0100
> +++ linux-2.6.24-rc4-IPv6-cache-based/fs/nfsd/nfsctl.c	2007-12-10 18:15:22.000000000 +0100
> @@ -37,6 +37,7 @@
>  #include <linux/nfsd/syscall.h>
>  
>  #include <asm/uaccess.h>
> +#include <net/ipv6.h>
>  
>  /*
>   *	We have a single directory with 9 nodes in it.
> @@ -222,6 +223,7 @@ static ssize_t write_getfs(struct file *
>  	struct auth_domain *clp;
>  	int err = 0;
>  	struct knfsd_fh *res;
> +	struct in6_addr in6;
>  
>  	if (size < sizeof(*data))
>  		return -EINVAL;
> @@ -236,7 +238,13 @@ static ssize_t write_getfs(struct file *
>  	res = (struct knfsd_fh*)buf;
>  
>  	exp_readlock();
> -	if (!(clp = auth_unix_lookup(sin->sin_addr)))
> +
> +	/* IPv6 address mapping */
> +	ipv6_addr_set(&in6, 0, 0,
> +			htonl(0x0000FFFF),
> +			(((struct sockaddr_in *)&data->gd_addr)->sin_addr.s_addr));
> +
> +	if (!(clp = auth_unix_lookup(in6)))
>  		err = -EPERM;
>  	else {
>  		err = exp_rootfh(clp, data->gd_path, res, data->gd_maxlen);
> @@ -257,6 +265,7 @@ static ssize_t write_getfd(struct file *
>  	int err = 0;
>  	struct knfsd_fh fh;
>  	char *res;
> +	struct in6_addr in6;
>  
>  	if (size < sizeof(*data))
>  		return -EINVAL;
> @@ -271,7 +280,12 @@ static ssize_t write_getfd(struct file *
>  	res = buf;
>  	sin = (struct sockaddr_in *)&data->gd_addr;
>  	exp_readlock();
> -	if (!(clp = auth_unix_lookup(sin->sin_addr)))
> +	/* IPv6 address mapping */
> +	ipv6_addr_set(&in6, 0, 0,
> +			htonl(0x0000FFFF),
> +			(((struct sockaddr_in *)&data->gd_addr)->sin_addr.s_addr));
> +
> +	if (!(clp = auth_unix_lookup(in6)))
>  		err = -EPERM;
>  	else {
>  		err = exp_rootfh(clp, data->gd_path, &fh, NFS_FHSIZE);
> diff -p -u -r -N linux-2.6.24-rc4/include/linux/sunrpc/svcauth.h linux-2.6.24-rc4-IPv6-cache-based/include/linux/sunrpc/svcauth.h
> --- linux-2.6.24-rc4/include/linux/sunrpc/svcauth.h	2007-12-10 16:01:43.000000000 +0100
> +++ linux-2.6.24-rc4-IPv6-cache-based/include/linux/sunrpc/svcauth.h	2007-12-10 17:09:34.000000000 +0100
> @@ -120,10 +120,10 @@ extern void	svc_auth_unregister(rpc_auth
>  
>  extern struct auth_domain *unix_domain_find(char *name);
>  extern void auth_domain_put(struct auth_domain *item);
> -extern int auth_unix_add_addr(struct in_addr addr, struct auth_domain *dom);
> +extern int auth_unix_add_addr(struct in6_addr *addr, struct auth_domain *dom);
>  extern struct auth_domain *auth_domain_lookup(char *name, struct auth_domain *new);
>  extern struct auth_domain *auth_domain_find(char *name);
> -extern struct auth_domain *auth_unix_lookup(struct in_addr addr);
> +extern struct auth_domain *auth_unix_lookup(struct in6_addr *addr);
>  extern int auth_unix_forget_old(struct auth_domain *dom);
>  extern void svcauth_unix_purge(void);
>  extern void svcauth_unix_info_release(void *);
> diff -p -u -r -N linux-2.6.24-rc4/net/sunrpc/svcauth_unix.c linux-2.6.24-rc4-IPv6-cache-based/net/sunrpc/svcauth_unix.c
> --- linux-2.6.24-rc4/net/sunrpc/svcauth_unix.c	2007-12-10 16:01:46.000000000 +0100
> +++ linux-2.6.24-rc4-IPv6-cache-based/net/sunrpc/svcauth_unix.c	2007-12-10 17:38:50.000000000 +0100
> @@ -11,7 +11,8 @@
>  #include <linux/hash.h>
>  #include <linux/string.h>
>  #include <net/sock.h>
> -
> +#include <net/ipv6.h>
> +#include <linux/kernel.h>
>  #define RPCDBG_FACILITY	RPCDBG_AUTH
>  
>  
> @@ -84,7 +85,7 @@ static void svcauth_unix_domain_release(
>  struct ip_map {
>  	struct cache_head	h;
>  	char			m_class[8]; /* e.g. "nfsd" */
> -	struct in_addr		m_addr;
> +	struct in6_addr		m_addr;
>  	struct unix_domain	*m_client;
>  	int			m_add_change;
>  };
> @@ -112,12 +113,19 @@ static inline int hash_ip(__be32 ip)
>  	return (hash ^ (hash>>8)) & 0xff;
>  }
>  #endif
> +static inline int hash_ip6(struct in6_addr ip)
> +{
> +	return (hash_ip(ip.s6_addr32[0]) ^
> +		hash_ip(ip.s6_addr32[1]) ^
> +		hash_ip(ip.s6_addr32[2]) ^
> +		hash_ip(ip.s6_addr32[3]));
> +}
>  static int ip_map_match(struct cache_head *corig, struct cache_head *cnew)
>  {
>  	struct ip_map *orig = container_of(corig, struct ip_map, h);
>  	struct ip_map *new = container_of(cnew, struct ip_map, h);
>  	return strcmp(orig->m_class, new->m_class) == 0
> -		&& orig->m_addr.s_addr == new->m_addr.s_addr;
> +		&& ipv6_addr_equal(&orig->m_addr, &new->m_addr);
>  }
>  static void ip_map_init(struct cache_head *cnew, struct cache_head *citem)
>  {
> @@ -125,7 +133,7 @@ static void ip_map_init(struct cache_hea
>  	struct ip_map *item = container_of(citem, struct ip_map, h);
>  
>  	strcpy(new->m_class, item->m_class);
> -	new->m_addr.s_addr = item->m_addr.s_addr;
> +	ipv6_addr_copy(&new->m_addr, &item->m_addr);
>  }
>  static void update(struct cache_head *cnew, struct cache_head *citem)
>  {
> @@ -149,22 +157,24 @@ static void ip_map_request(struct cache_
>  				  struct cache_head *h,
>  				  char **bpp, int *blen)
>  {
> -	char text_addr[20];
> +	char text_addr[40];
>  	struct ip_map *im = container_of(h, struct ip_map, h);
> -	__be32 addr = im->m_addr.s_addr;
> -
> -	snprintf(text_addr, 20, "%u.%u.%u.%u",
> -		 ntohl(addr) >> 24 & 0xff,
> -		 ntohl(addr) >> 16 & 0xff,
> -		 ntohl(addr) >>  8 & 0xff,
> -		 ntohl(addr) >>  0 & 0xff);
>  
> +	if (ipv6_addr_v4mapped(&(im->m_addr))) {
> +		snprintf(text_addr, 20, NIPQUAD_FMT,
> +				ntohl(im->m_addr.s6_addr32[3]) >> 24 & 0xff,
> +				ntohl(im->m_addr.s6_addr32[3]) >> 16 & 0xff,
> +				ntohl(im->m_addr.s6_addr32[3]) >>  8 & 0xff,
> +				ntohl(im->m_addr.s6_addr32[3]) >>  0 & 0xff);
> +	} else {
> +		snprintf(text_addr, 40, NIP6_FMT, NIP6(im->m_addr));
> +	}
>  	qword_add(bpp, blen, im->m_class);
>  	qword_add(bpp, blen, text_addr);
>  	(*bpp)[-1] = '\n';
>  }
>  
> -static struct ip_map *ip_map_lookup(char *class, struct in_addr addr);
> +static struct ip_map *ip_map_lookup(char *class, struct in6_addr *addr);
>  static int ip_map_update(struct ip_map *ipm, struct unix_domain *udom, time_t expiry);
>  
>  static int ip_map_parse(struct cache_detail *cd,
> @@ -175,10 +185,10 @@ static int ip_map_parse(struct cache_det
>  	 * for scratch: */
>  	char *buf = mesg;
>  	int len;
> -	int b1,b2,b3,b4;
> +	int b1, b2, b3, b4, b5, b6, b7, b8;
>  	char c;
>  	char class[8];
> -	struct in_addr addr;
> +	struct in6_addr addr;
>  	int err;
>  
>  	struct ip_map *ipmp;
> @@ -197,9 +207,26 @@ static int ip_map_parse(struct cache_det
>  	len = qword_get(&mesg, buf, mlen);
>  	if (len <= 0) return -EINVAL;
>  
> -	if (sscanf(buf, "%u.%u.%u.%u%c", &b1, &b2, &b3, &b4, &c) != 4)
> +	if (sscanf(buf, NIPQUAD_FMT "%c", &b1, &b2, &b3, &b4, &c) == 4) {
> +		addr.s6_addr32[0] = 0;
> +		addr.s6_addr32[1] = 0;
> +		addr.s6_addr32[2] = htonl(0xffff);
> +		addr.s6_addr32[3] =
> +			htonl((((((b1<<8)|b2)<<8)|b3)<<8)|b4);
> +       } else if (sscanf(buf, NIP6_FMT "%c",
> +			&b1, &b2, &b3, &b4, &b5, &b6, &b7, &b8, &c) == 8) {
> +		addr.s6_addr16[0] = htons(b1);
> +		addr.s6_addr16[1] = htons(b2);
> +		addr.s6_addr16[2] = htons(b3);
> +		addr.s6_addr16[3] = htons(b4);
> +		addr.s6_addr16[4] = htons(b5);
> +		addr.s6_addr16[5] = htons(b6);
> +		addr.s6_addr16[6] = htons(b7);
> +		addr.s6_addr16[7] = htons(b8);
> +       } else
>  		return -EINVAL;
>  
> +
>  	expiry = get_expiry(&mesg);
>  	if (expiry ==0)
>  		return -EINVAL;
> @@ -215,10 +242,7 @@ static int ip_map_parse(struct cache_det
>  	} else
>  		dom = NULL;
>  
> -	addr.s_addr =
> -		htonl((((((b1<<8)|b2)<<8)|b3)<<8)|b4);
> -
> -	ipmp = ip_map_lookup(class,addr);
> +	ipmp = ip_map_lookup(class, &addr);
>  	if (ipmp) {
>  		err = ip_map_update(ipmp,
>  			     container_of(dom, struct unix_domain, h),
> @@ -238,7 +262,7 @@ static int ip_map_show(struct seq_file *
>  		       struct cache_head *h)
>  {
>  	struct ip_map *im;
> -	struct in_addr addr;
> +	struct in6_addr addr;
>  	char *dom = "-no-domain-";
>  
>  	if (h == NULL) {
> @@ -247,20 +271,24 @@ static int ip_map_show(struct seq_file *
>  	}
>  	im = container_of(h, struct ip_map, h);
>  	/* class addr domain */
> -	addr = im->m_addr;
> +	ipv6_addr_copy(&addr, &im->m_addr);
>  
>  	if (test_bit(CACHE_VALID, &h->flags) &&
>  	    !test_bit(CACHE_NEGATIVE, &h->flags))
>  		dom = im->m_client->h.name;
>  
> -	seq_printf(m, "%s %d.%d.%d.%d %s\n",
> -		   im->m_class,
> -		   ntohl(addr.s_addr) >> 24 & 0xff,
> -		   ntohl(addr.s_addr) >> 16 & 0xff,
> -		   ntohl(addr.s_addr) >>  8 & 0xff,
> -		   ntohl(addr.s_addr) >>  0 & 0xff,
> -		   dom
> -		   );
> +	if (ipv6_addr_v4mapped(&addr)) {
> +		seq_printf(m, "%s" NIPQUAD_FMT "%s\n",
> +			im->m_class,
> +			ntohl(addr.s6_addr32[3]) >> 24 & 0xff,
> +			ntohl(addr.s6_addr32[3]) >> 16 & 0xff,
> +			ntohl(addr.s6_addr32[3]) >>  8 & 0xff,
> +			ntohl(addr.s6_addr32[3]) >>  0 & 0xff,
> +			dom);
> +	} else {
> +		seq_printf(m, "%s" NIP6_FMT "%s\n",
> +			im->m_class, NIP6(addr), dom);
> +	}
>  	return 0;
>  }
>  
> @@ -280,16 +308,16 @@ struct cache_detail ip_map_cache = {
>  	.alloc		= ip_map_alloc,
>  };
>  
> -static struct ip_map *ip_map_lookup(char *class, struct in_addr addr)
> +static struct ip_map *ip_map_lookup(char *class, struct in6_addr *addr)
>  {
>  	struct ip_map ip;
>  	struct cache_head *ch;
>  
>  	strcpy(ip.m_class, class);
> -	ip.m_addr = addr;
> +	ipv6_addr_copy(&ip.m_addr, addr);
>  	ch = sunrpc_cache_lookup(&ip_map_cache, &ip.h,
>  				 hash_str(class, IP_HASHBITS) ^
> -				 hash_ip(addr.s_addr));
> +				 hash_ip6(*addr));
>  
>  	if (ch)
>  		return container_of(ch, struct ip_map, h);
> @@ -318,14 +346,14 @@ static int ip_map_update(struct ip_map *
>  	ch = sunrpc_cache_update(&ip_map_cache,
>  				 &ip.h, &ipm->h,
>  				 hash_str(ipm->m_class, IP_HASHBITS) ^
> -				 hash_ip(ipm->m_addr.s_addr));
> +				 hash_ip6(ipm->m_addr));
>  	if (!ch)
>  		return -ENOMEM;
>  	cache_put(ch, &ip_map_cache);
>  	return 0;
>  }
>  
> -int auth_unix_add_addr(struct in_addr addr, struct auth_domain *dom)
> +int auth_unix_add_addr(struct in6_addr *addr, struct auth_domain *dom)
>  {
>  	struct unix_domain *udom;
>  	struct ip_map *ipmp;
> @@ -352,7 +380,7 @@ int auth_unix_forget_old(struct auth_dom
>  	return 0;
>  }
>  
> -struct auth_domain *auth_unix_lookup(struct in_addr addr)
> +struct auth_domain *auth_unix_lookup(struct in6_addr *addr)
>  {
>  	struct ip_map *ipm;
>  	struct auth_domain *rv;
> @@ -641,9 +669,24 @@ static int unix_gid_find(uid_t uid, stru
>  int
>  svcauth_unix_set_client(struct svc_rqst *rqstp)
>  {
> -	struct sockaddr_in *sin = svc_addr_in(rqstp);
> +	struct sockaddr_in *sin;
> +	struct sockaddr_in6 *sin6, sin6_storage;
>  	struct ip_map *ipm;
>  
> +	switch (rqstp->rq_addr.ss_family) {
> +	case AF_INET:
> +		sin = svc_addr_in(rqstp);
> +		sin6 = &sin6_storage;
> +		ipv6_addr_set(&sin6->sin6_addr, 0, 0,
> +				htonl(0x0000FFFF), sin->sin_addr.s_addr);
> +		break;
> +	case AF_INET6:
> +		sin6 = svc_addr_in6(rqstp);
> +		break;
> +	default:
> +		BUG();
> +	}
> +
>  	rqstp->rq_client = NULL;
>  	if (rqstp->rq_proc == 0)
>  		return SVC_OK;
> @@ -651,7 +694,7 @@ svcauth_unix_set_client(struct svc_rqst 
>  	ipm = ip_map_cached_get(rqstp);
>  	if (ipm == NULL)
>  		ipm = ip_map_lookup(rqstp->rq_server->sv_program->pg_class,
> -				    sin->sin_addr);
> +				    &sin6->sin6_addr);
>  
>  	if (ipm == NULL)
>  		return SVC_DENIED;

_______________________________________________
NFSv4 mailing list
NFSv4@linux-nfs.org
http://linux-nfs.org/cgi-bin/mailman/listinfo/nfsv4

^ permalink raw reply

* Re: "ip neigh show" not showing arp cache entries?
From: Chris Friesen @ 2007-12-10 17:54 UTC (permalink / raw)
  To: Chris Friesen; +Cc: linux-kernel, netdev
In-Reply-To: <475D7901.1040900@nortel.com>

Chris Friesen wrote:
> 
> I'm seeing some strange behaviour on a 2.6.14 ppc64 system.  If I run 
> "ip neigh show" it prints out nothing, but if I run "arp" then I see the 
> other nodes on the local network.
> 
> 
> root@base0-0-0-5-0-11-1:/root> ip neigh show
> root@base0-0-0-5-0-11-1:/root> arp -n
> Address                  HWtype  HWaddress           Flags Mask    Iface
> 172.24.132.0             ether   00:01:AF:14:E8:DA   C    bond0
> 172.24.132.1                     (incomplete)    bond0
> 172.24.136.0             ether   00:C0:8B:07:B3:7E   C    bond0
> 172.24.132.4             ether   00:01:AF:14:E8:DA   C    bond0
> 172.24.132.2             ether   00:01:AF:14:E8:DA   C    bond0
> 
> 
> Any ideas what's going on here?

I've got some further information.  If I look for a specific address, it 
seems to work:

root@base0-0-0-5-0-11-1:/root> ip neigh show 172.24.136.0
172.24.136.0 dev bond0 lladdr 00:c0:8b:07:b3:7e REACHABLE


In the above scenario, the arp cache lists the device as reachable via 
bond0.  If I search the arp cache to see whether the address is 
reachable from one of bond0's slave devices, should it come back 
positive or negative?

Chris

^ permalink raw reply

* Re: [PATCH 2.6.25] netns: struct net content re-work
From: Kirill Korotaev @ 2007-12-10 17:50 UTC (permalink / raw)
  To: Daniel Lezcano; +Cc: Denis V. Lunev, containers, netdev, davem, herbert
In-Reply-To: <475D7849.3030206@fr.ibm.com>

Daniel Lezcano wrote:
> Denis V. Lunev wrote:
> 
>>Recently David Miller and Herbert Xu pointed out that struct net becomes
>>overbloated and un-maintainable. There are two solutions:
>>- provide a pointer to a network subsystem definition from struct net.
>>  This costs an additional dereferrence
>>- place sub-system definition into the structure itself. This will speedup
>>  run-time access at the cost of recompilation time
>>
>>The second approach looks better for us. 
> 
> 
> Yes, we do not need/want a pointer in this structure and add more 
> dereference in the network code.
> 
> 
>>Other sub-systems will be converted
>>to this approach if this will be accepted :)
>>
>>Signed-off-by: Denis V. Lunev <den@openvz.org>
>>---
>>diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
>>index b62e31f..f60e1ce 100644
>>--- a/include/net/net_namespace.h
>>+++ b/include/net/net_namespace.h
>>@@ -8,6 +8,8 @@
>> #include <linux/workqueue.h>
>> #include <linux/list.h>
>>
>>+#include <net/netns/unix.h>
>>+
>> struct proc_dir_entry;
>> struct net_device;
>> struct sock;
>>@@ -46,8 +48,7 @@ struct net {
>> 	struct hlist_head	packet_sklist;
>>
>> 	/* unix sockets */
>>-	int			sysctl_unix_max_dgram_qlen;
>>-	struct ctl_table_header	*unix_ctl;
>>+	struct netns_unix	unx;
> 
> 
> Can you change this from unx to unix ?

no, it won't compile. Guess why :)

> If you encapsulate the structure definitions per subsystem, you can drop 
> the unix prefix in the variable declaration.
> 
> Instead of having:
> 	netns->unix->unix_ctl
> you will have:
> 	netns->unix->ctl

agree.

Kirill

^ permalink raw reply

* htb and UDP packages bigger than 1500
From: Arkadiusz Miskiewicz @ 2007-12-10 17:10 UTC (permalink / raw)
  To: netdev

Hello,

I noticed that HTB doesn't properly limit traffic if someone sends UDP 
packages bigger than 1500. 

Does HTB have some problems/known limits in this area?

There is other traffic in that class and when I drop udp packets bigger than 
1500 then remaining traffic is limited properly to correct value.

udp part of tcpdump log:
17:35:24.041364 IP 172.16.4.23.3185 > 80.51.230.58.9267: UDP, length 35
17:35:24.048834 IP 172.16.4.23.46073 > 83.53.197.205.50882: UDP, length 35
17:35:24.071234 IP 172.16.4.23.2904 > 81.38.28.69.26349: UDP, length 35
17:35:24.076924 IP 201.232.209.115.50750 > 172.16.4.23.57590: UDP, length 8251
17:35:24.140895 IP 90.242.120.252.11982 > 172.16.4.23.19111: UDP, length 35
17:35:24.140976 IP 79.186.64.121.47130 > 172.16.4.23.19111: UDP, length 35
17:35:24.141039 IP 24.150.182.77.55984 > 172.16.4.23.41279: UDP, length 29
17:35:24.141120 IP 83.37.212.153.25153 > 172.16.4.23.32824: UDP, length 8251
17:35:24.154874 IP 172.16.4.23.19111 > 90.242.120.252.11982: UDP, length 8251
17:35:24.210940 IP 83.8.18.150.28955 > 172.16.4.23.24825: UDP, length 8251
17:35:24.240382 IP 172.16.4.23.19111 > 79.186.64.121.47130: UDP, length 8251
17:35:24.272529 IP 83.19.224.219.32977 > 172.16.4.23.19111: UDP, length 35
17:35:24.307164 IP 85.219.10.150.18601 > 172.16.4.23.51986: UDP, length 8251
17:35:24.312335 IP 83.26.249.97.10137 > 172.16.4.23.9383: UDP, length 8251
17:35:24.404250 IP 83.19.224.11.1833 > 172.16.4.23.21258: UDP, length 8251
17:35:24.467562 IP 196.206.89.182.58764 > 172.16.4.23.19111: UDP, length 35
17:35:24.560058 IP 172.16.4.23.50417 > 82.5.204.164.1024: UDP, length 25
17:35:24.563842 IP 172.16.4.23.24825 > 83.8.18.150.28955: UDP, length 35
17:35:24.567316 IP 172.16.4.23.59727 > 195.60.65.36.61323: UDP, length 35
17:35:24.569976 IP 83.11.67.228.31949 > 172.16.4.23.56823: UDP, length 8251
17:35:24.617104 IP 172.16.4.23.28945 > 76.11.24.115.13887: UDP, length 29
17:35:24.619235 IP 172.16.4.23.21258 > 83.19.224.11.1833: UDP, length 35
17:35:24.626488 IP 172.16.4.23.9383 > 83.26.249.97.10137: UDP, length 35
17:35:24.640367 IP 172.16.4.23.47366 > 91.146.230.1.38928: UDP, length 25
17:35:24.644314 IP 90.242.120.252.1955 > 172.16.4.23.19111: UDP, length 35
17:35:24.652024 IP 81.184.124.145.22454 > 172.16.4.23.57089: UDP, length 8251

-- 
Arkadiusz Miśkiewicz        PLD/Linux Team
arekm / maven.pl            http://ftp.pld-linux.org/

^ permalink raw reply

* Re: [PATCH 2.6.25] netns: struct net content re-work
From: Daniel Lezcano @ 2007-12-10 17:32 UTC (permalink / raw)
  To: Denis V. Lunev; +Cc: davem, containers, devel, netdev, herbert
In-Reply-To: <20071210163645.GA24030@iris.sw.ru>

Denis V. Lunev wrote:
> Recently David Miller and Herbert Xu pointed out that struct net becomes
> overbloated and un-maintainable. There are two solutions:
> - provide a pointer to a network subsystem definition from struct net.
>   This costs an additional dereferrence
> - place sub-system definition into the structure itself. This will speedup
>   run-time access at the cost of recompilation time
> 
> The second approach looks better for us. 

Yes, we do not need/want a pointer in this structure and add more 
dereference in the network code.

> Other sub-systems will be converted
> to this approach if this will be accepted :)
> 
> Signed-off-by: Denis V. Lunev <den@openvz.org>
> ---
> diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
> index b62e31f..f60e1ce 100644
> --- a/include/net/net_namespace.h
> +++ b/include/net/net_namespace.h
> @@ -8,6 +8,8 @@
>  #include <linux/workqueue.h>
>  #include <linux/list.h>
> 
> +#include <net/netns/unix.h>
> +
>  struct proc_dir_entry;
>  struct net_device;
>  struct sock;
> @@ -46,8 +48,7 @@ struct net {
>  	struct hlist_head	packet_sklist;
> 
>  	/* unix sockets */
> -	int			sysctl_unix_max_dgram_qlen;
> -	struct ctl_table_header	*unix_ctl;
> +	struct netns_unix	unx;

Can you change this from unx to unix ?

If you encapsulate the structure definitions per subsystem, you can drop 
the unix prefix in the variable declaration.

Instead of having:
	netns->unix->unix_ctl
you will have:
	netns->unix->ctl

>  };
> 
>  #ifdef CONFIG_NET
> diff --git a/include/net/netns/unix.h b/include/net/netns/unix.h
> new file mode 100644
> index 0000000..27b4e7f
> --- /dev/null
> +++ b/include/net/netns/unix.h
> @@ -0,0 +1,13 @@
> +/*
> + * Unix network namespace
> + */
> +#ifndef __NETNS_UNIX_H__
> +#define __NETNS_UNIX_H__
> +
> +struct ctl_table_header;
> +struct netns_unix {
> +	int			sysctl_unix_max_dgram_qlen;
> +	struct ctl_table_header	*unix_ctl;
> +};
> +
> +#endif /* __NETNS_UNIX_H__ */

If I follow the logic, we will have a file per subsystem. These files 
will be very small, no ?
IMHO, having the structure defined in net_namespace.h is enough.

> diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
> index b8a2189..06f7ec8 100644
> --- a/net/unix/af_unix.c
> +++ b/net/unix/af_unix.c
> @@ -592,7 +592,7 @@ static struct sock * unix_create1(struct net *net, struct socket *sock)
>  				&af_unix_sk_receive_queue_lock_key);
> 
>  	sk->sk_write_space	= unix_write_space;
> -	sk->sk_max_ack_backlog	= net->sysctl_unix_max_dgram_qlen;
> +	sk->sk_max_ack_backlog	= net->unx.sysctl_unix_max_dgram_qlen;
>  	sk->sk_destruct		= unix_sock_destructor;
>  	u	  = unix_sk(sk);
>  	u->dentry = NULL;
> @@ -2138,7 +2138,7 @@ static int unix_net_init(struct net *net)
>  {
>  	int error = -ENOMEM;
> 
> -	net->sysctl_unix_max_dgram_qlen = 10;
> +	net->unx.sysctl_unix_max_dgram_qlen = 10;
>  	if (unix_sysctl_register(net))
>  		goto out;
> 
> diff --git a/net/unix/sysctl_net_unix.c b/net/unix/sysctl_net_unix.c
> index 553ef6a..fbddfb5 100644
> --- a/net/unix/sysctl_net_unix.c
> +++ b/net/unix/sysctl_net_unix.c
> @@ -18,7 +18,7 @@ static ctl_table unix_table[] = {
>  	{
>  		.ctl_name	= NET_UNIX_MAX_DGRAM_QLEN,
>  		.procname	= "max_dgram_qlen",
> -		.data		= &init_net.sysctl_unix_max_dgram_qlen,
> +		.data		= &init_net.unx.sysctl_unix_max_dgram_qlen,
>  		.maxlen		= sizeof(int),
>  		.mode		= 0644,
>  		.proc_handler	= &proc_dointvec
> @@ -40,9 +40,9 @@ int unix_sysctl_register(struct net *net)
>  	if (table == NULL)
>  		goto err_alloc;
> 
> -	table[0].data = &net->sysctl_unix_max_dgram_qlen;
> -	net->unix_ctl = register_net_sysctl_table(net, unix_path, table);
> -	if (net->unix_ctl == NULL)
> +	table[0].data = &net->unx.sysctl_unix_max_dgram_qlen;
> +	net->unx.unix_ctl = register_net_sysctl_table(net, unix_path, table);
> +	if (net->unx.unix_ctl == NULL)
>  		goto err_reg;
> 
>  	return 0;
> @@ -57,8 +57,8 @@ void unix_sysctl_unregister(struct net *net)
>  {
>  	struct ctl_table *table;
> 
> -	table = net->unix_ctl->ctl_table_arg;
> -	unregister_sysctl_table(net->unix_ctl);
> +	table = net->unx.unix_ctl->ctl_table_arg;
> +	unregister_sysctl_table(net->unx.unix_ctl);
>  	kfree(table);
>  }
> 
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 


^ permalink raw reply

* "ip neigh show" not showing arp cache entries?
From: Chris Friesen @ 2007-12-10 17:36 UTC (permalink / raw)
  To: linux-kernel, netdev


I'm seeing some strange behaviour on a 2.6.14 ppc64 system.  If I run 
"ip neigh show" it prints out nothing, but if I run "arp" then I see the 
other nodes on the local network.


root@base0-0-0-5-0-11-1:/root> ip neigh show
root@base0-0-0-5-0-11-1:/root> arp -n
Address                  HWtype  HWaddress           Flags Mask 
    Iface
172.24.132.0             ether   00:01:AF:14:E8:DA   C 
    bond0
172.24.132.1                     (incomplete) 
    bond0
172.24.136.0             ether   00:C0:8B:07:B3:7E   C 
    bond0
172.24.132.4             ether   00:01:AF:14:E8:DA   C 
    bond0
172.24.132.2             ether   00:01:AF:14:E8:DA   C 
    bond0


Any ideas what's going on here?

Thanks,

Chris

^ permalink raw reply

* [PATCH 2.6.25] UNIX: remove unused declaration of sysctl_unix_max_dgram_qlen
From: Denis V. Lunev @ 2007-12-10 16:37 UTC (permalink / raw)
  To: davem; +Cc: containers, devel, netdev

Recently David Miller and Herbert Xu pointed out that struct net becomes
overbloated and un-maintainable. There are two solutions:
- provide a pointer to a network subsystem definition from struct net.
  This costs an additional dereferrence
- place sub-system definition into the structure itself. This will speedup
  run-time access at the cost of recompilation time

The second approach looks better for us. Other sub-systems will be converted
to this approach if this will be accepted :)

Signed-off-by: Denis V. Lunev <den@openvz.org>
---
diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
index b62e31f..f60e1ce 100644
--- a/include/net/net_namespace.h
+++ b/include/net/net_namespace.h
@@ -8,6 +8,8 @@
 #include <linux/workqueue.h>
 #include <linux/list.h>
 
+#include <net/netns/unix.h>
+
 struct proc_dir_entry;
 struct net_device;
 struct sock;
@@ -46,8 +48,7 @@ struct net {
 	struct hlist_head	packet_sklist;
 
 	/* unix sockets */
-	int			sysctl_unix_max_dgram_qlen;
-	struct ctl_table_header	*unix_ctl;
+	struct netns_unix	unx;
 };
 
 #ifdef CONFIG_NET
diff --git a/include/net/netns/unix.h b/include/net/netns/unix.h
new file mode 100644
index 0000000..27b4e7f
--- /dev/null
+++ b/include/net/netns/unix.h
@@ -0,0 +1,13 @@
+/*
+ * Unix network namespace
+ */
+#ifndef __NETNS_UNIX_H__
+#define __NETNS_UNIX_H__
+
+struct ctl_table_header;
+struct netns_unix {
+	int			sysctl_unix_max_dgram_qlen;
+	struct ctl_table_header	*unix_ctl;
+};
+
+#endif /* __NETNS_UNIX_H__ */
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index b8a2189..06f7ec8 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -592,7 +592,7 @@ static struct sock * unix_create1(struct net *net, struct socket *sock)
 				&af_unix_sk_receive_queue_lock_key);
 
 	sk->sk_write_space	= unix_write_space;
-	sk->sk_max_ack_backlog	= net->sysctl_unix_max_dgram_qlen;
+	sk->sk_max_ack_backlog	= net->unx.sysctl_unix_max_dgram_qlen;
 	sk->sk_destruct		= unix_sock_destructor;
 	u	  = unix_sk(sk);
 	u->dentry = NULL;
@@ -2138,7 +2138,7 @@ static int unix_net_init(struct net *net)
 {
 	int error = -ENOMEM;
 
-	net->sysctl_unix_max_dgram_qlen = 10;
+	net->unx.sysctl_unix_max_dgram_qlen = 10;
 	if (unix_sysctl_register(net))
 		goto out;
 
diff --git a/net/unix/sysctl_net_unix.c b/net/unix/sysctl_net_unix.c
index 553ef6a..fbddfb5 100644
--- a/net/unix/sysctl_net_unix.c
+++ b/net/unix/sysctl_net_unix.c
@@ -18,7 +18,7 @@ static ctl_table unix_table[] = {
 	{
 		.ctl_name	= NET_UNIX_MAX_DGRAM_QLEN,
 		.procname	= "max_dgram_qlen",
-		.data		= &init_net.sysctl_unix_max_dgram_qlen,
+		.data		= &init_net.unx.sysctl_unix_max_dgram_qlen,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
 		.proc_handler	= &proc_dointvec
@@ -40,9 +40,9 @@ int unix_sysctl_register(struct net *net)
 	if (table == NULL)
 		goto err_alloc;
 
-	table[0].data = &net->sysctl_unix_max_dgram_qlen;
-	net->unix_ctl = register_net_sysctl_table(net, unix_path, table);
-	if (net->unix_ctl == NULL)
+	table[0].data = &net->unx.sysctl_unix_max_dgram_qlen;
+	net->unx.unix_ctl = register_net_sysctl_table(net, unix_path, table);
+	if (net->unx.unix_ctl == NULL)
 		goto err_reg;
 
 	return 0;
@@ -57,8 +57,8 @@ void unix_sysctl_unregister(struct net *net)
 {
 	struct ctl_table *table;
 
-	table = net->unix_ctl->ctl_table_arg;
-	unregister_sysctl_table(net->unix_ctl);
+	table = net->unx.unix_ctl->ctl_table_arg;
+	unregister_sysctl_table(net->unx.unix_ctl);
 	kfree(table);
 }
 

^ permalink raw reply related

* [PATCH 2.6.25] netns: struct net content re-work
From: Denis V. Lunev @ 2007-12-10 16:36 UTC (permalink / raw)
  To: davem; +Cc: containers, devel, netdev, herbert

Recently David Miller and Herbert Xu pointed out that struct net becomes
overbloated and un-maintainable. There are two solutions:
- provide a pointer to a network subsystem definition from struct net.
  This costs an additional dereferrence
- place sub-system definition into the structure itself. This will speedup
  run-time access at the cost of recompilation time

The second approach looks better for us. Other sub-systems will be converted
to this approach if this will be accepted :)

Signed-off-by: Denis V. Lunev <den@openvz.org>
---
diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
index b62e31f..f60e1ce 100644
--- a/include/net/net_namespace.h
+++ b/include/net/net_namespace.h
@@ -8,6 +8,8 @@
 #include <linux/workqueue.h>
 #include <linux/list.h>
 
+#include <net/netns/unix.h>
+
 struct proc_dir_entry;
 struct net_device;
 struct sock;
@@ -46,8 +48,7 @@ struct net {
 	struct hlist_head	packet_sklist;
 
 	/* unix sockets */
-	int			sysctl_unix_max_dgram_qlen;
-	struct ctl_table_header	*unix_ctl;
+	struct netns_unix	unx;
 };
 
 #ifdef CONFIG_NET
diff --git a/include/net/netns/unix.h b/include/net/netns/unix.h
new file mode 100644
index 0000000..27b4e7f
--- /dev/null
+++ b/include/net/netns/unix.h
@@ -0,0 +1,13 @@
+/*
+ * Unix network namespace
+ */
+#ifndef __NETNS_UNIX_H__
+#define __NETNS_UNIX_H__
+
+struct ctl_table_header;
+struct netns_unix {
+	int			sysctl_unix_max_dgram_qlen;
+	struct ctl_table_header	*unix_ctl;
+};
+
+#endif /* __NETNS_UNIX_H__ */
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index b8a2189..06f7ec8 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -592,7 +592,7 @@ static struct sock * unix_create1(struct net *net, struct socket *sock)
 				&af_unix_sk_receive_queue_lock_key);
 
 	sk->sk_write_space	= unix_write_space;
-	sk->sk_max_ack_backlog	= net->sysctl_unix_max_dgram_qlen;
+	sk->sk_max_ack_backlog	= net->unx.sysctl_unix_max_dgram_qlen;
 	sk->sk_destruct		= unix_sock_destructor;
 	u	  = unix_sk(sk);
 	u->dentry = NULL;
@@ -2138,7 +2138,7 @@ static int unix_net_init(struct net *net)
 {
 	int error = -ENOMEM;
 
-	net->sysctl_unix_max_dgram_qlen = 10;
+	net->unx.sysctl_unix_max_dgram_qlen = 10;
 	if (unix_sysctl_register(net))
 		goto out;
 
diff --git a/net/unix/sysctl_net_unix.c b/net/unix/sysctl_net_unix.c
index 553ef6a..fbddfb5 100644
--- a/net/unix/sysctl_net_unix.c
+++ b/net/unix/sysctl_net_unix.c
@@ -18,7 +18,7 @@ static ctl_table unix_table[] = {
 	{
 		.ctl_name	= NET_UNIX_MAX_DGRAM_QLEN,
 		.procname	= "max_dgram_qlen",
-		.data		= &init_net.sysctl_unix_max_dgram_qlen,
+		.data		= &init_net.unx.sysctl_unix_max_dgram_qlen,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
 		.proc_handler	= &proc_dointvec
@@ -40,9 +40,9 @@ int unix_sysctl_register(struct net *net)
 	if (table == NULL)
 		goto err_alloc;
 
-	table[0].data = &net->sysctl_unix_max_dgram_qlen;
-	net->unix_ctl = register_net_sysctl_table(net, unix_path, table);
-	if (net->unix_ctl == NULL)
+	table[0].data = &net->unx.sysctl_unix_max_dgram_qlen;
+	net->unx.unix_ctl = register_net_sysctl_table(net, unix_path, table);
+	if (net->unx.unix_ctl == NULL)
 		goto err_reg;
 
 	return 0;
@@ -57,8 +57,8 @@ void unix_sysctl_unregister(struct net *net)
 {
 	struct ctl_table *table;
 
-	table = net->unix_ctl->ctl_table_arg;
-	unregister_sysctl_table(net->unix_ctl);
+	table = net->unx.unix_ctl->ctl_table_arg;
+	unregister_sysctl_table(net->unx.unix_ctl);
 	kfree(table);
 }
 

^ permalink raw reply related

* Re: routing policy based on u32 classifier
From: Marco Berizzi @ 2007-12-10 16:09 UTC (permalink / raw)
  To: Brian S Julin, netdev
In-Reply-To: <5A630F46702DD1498FFD48394B4A664C347275DE@john.ad.clarku.edu>

Brian S Julin wrote:

> Almost clear... why can you not just add "src <ADSL IP>" to
> the fwmark route to set the default source address for locally
> originating packets?

IIRC, it doesn't work because netfilter isn't called
in ip source address selection.



^ permalink raw reply

* Re: [patch 0/5] ipv6:  make af_inet6 subsystems to return an error at init
From: Daniel Lezcano @ 2007-12-10 15:32 UTC (permalink / raw)
  To: Daniel Lezcano; +Cc: davem, yoshfuji, pekkas, netdev
In-Reply-To: <20071210150910.440970057@ICON-9-164-138-215.megacenter.de.ibm.com>

Daniel Lezcano wrote:
> This patchset continue the work to make the different af_inet6 
> subsystems initialization functions to return an error code and
> to handle the error to fails safely.
> 
> It takes into account:
> 	* flowlabel
> 	* exthdrs
> 	* frag
> 	* udp
> 	* udplite
> 	* tcp
> 	* raw

I just noticed that I forgot to put ipv6 under bracket.
Sorry for that :(

Should I resend the patchset ?

^ permalink raw reply

* Re: routing policy based on u32 classifier
From: Marco Berizzi @ 2007-12-10 15:20 UTC (permalink / raw)
  To: Brian S Julin, netdev
In-Reply-To: <5A630F46702DD1498FFD48394B4A664C347275DD@john.ad.clarku.edu>

Brian S Julin wrote:

Marco wrote:

> > Hello everybody.
> > Kindly, I would like to know if the is any plan to add this feature
to a > > future kernel release.
> > I know that fwmark is able to do this, but there is the limitation
in
> > source ip address selection.

> Could you explain the limitation?

Indeed.
Here is an example:

    hdsl|  |adsl
    line|  |line
        |  |
      +------+
      |      |
      |SQUID |
      |      |
      +------+
          |
  internal|
    lan   |


The linux default gateway point to the hdsl
router. I want to redirect the squid http
traffic (running on the same host) to the adsl
line. So I create a routing table (adsl table)
and I put a default route to the adsl router.
I mark the http traffic. I insert a rule
based on fwmark which select the 'adsl table'.
So far, so good. But, squid will select the
source ip address from the hdsl network class,
because it is the default gateway.
Then, the local generated packets must be SNATed
with the adsl ip.
Is it clear?



^ permalink raw reply

* [patch 4/5] ipv6:  make inet6_register_protosw to return an error code
From: Daniel Lezcano @ 2007-12-10 15:09 UTC (permalink / raw)
  To: davem; +Cc: yoshfuji, pekkas, netdev
In-Reply-To: <20071210150910.440970057@ICON-9-164-138-215.megacenter.de.ibm.com>

[-- Attachment #1: make-inet6_register_protosw-return-an-error-code.patch --]
[-- Type: text/plain, Size: 2249 bytes --]

This patch makes the inet6_register_protosw to return an error code.
The different protocols can be aware the registration was successful or
not and can pass the error to the initial caller, af_inet6.

Signed-off-by: Daniel Lezcano <dlezcano@fr.ibm.com>
---
 include/net/protocol.h |    2 +-
 net/ipv6/af_inet6.c    |   11 +++++++----
 2 files changed, 8 insertions(+), 5 deletions(-)

Index: net-2.6.25/include/net/protocol.h
===================================================================
--- net-2.6.25.orig/include/net/protocol.h
+++ net-2.6.25/include/net/protocol.h
@@ -102,7 +102,7 @@ extern void	inet_unregister_protosw(stru
 #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
 extern int	inet6_add_protocol(struct inet6_protocol *prot, unsigned char num);
 extern int	inet6_del_protocol(struct inet6_protocol *prot, unsigned char num);
-extern void	inet6_register_protosw(struct inet_protosw *p);
+extern int	inet6_register_protosw(struct inet_protosw *p);
 extern void	inet6_unregister_protosw(struct inet_protosw *p);
 #endif
 
Index: net-2.6.25/net/ipv6/af_inet6.c
===================================================================
--- net-2.6.25.orig/net/ipv6/af_inet6.c
+++ net-2.6.25/net/ipv6/af_inet6.c
@@ -565,21 +565,23 @@ static struct inet_protosw rawv6_protosw
 	.flags		= INET_PROTOSW_REUSE,
 };
 
-void
-inet6_register_protosw(struct inet_protosw *p)
+int inet6_register_protosw(struct inet_protosw *p)
 {
 	struct list_head *lh;
 	struct inet_protosw *answer;
-	int protocol = p->protocol;
 	struct list_head *last_perm;
+	int protocol = p->protocol;
+	int ret;
 
 	spin_lock_bh(&inetsw6_lock);
 
+	ret = -EINVAL;
 	if (p->type >= SOCK_MAX)
 		goto out_illegal;
 
 	/* If we are trying to override a permanent protocol, bail. */
 	answer = NULL;
+	ret = -EPERM;
 	last_perm = &inetsw6[p->type];
 	list_for_each(lh, &inetsw6[p->type]) {
 		answer = list_entry(lh, struct inet_protosw, list);
@@ -603,9 +605,10 @@ inet6_register_protosw(struct inet_proto
 	 * system automatically returns to the old behavior.
 	 */
 	list_add_rcu(&p->list, last_perm);
+	ret = 0;
 out:
 	spin_unlock_bh(&inetsw6_lock);
-	return;
+	return ret;
 
 out_permanent:
 	printk(KERN_ERR "Attempt to override permanent protocol %d.\n",

-- 

^ permalink raw reply

* [patch 3/5] ipv6:  make frag to return an error at initialization
From: Daniel Lezcano @ 2007-12-10 15:09 UTC (permalink / raw)
  To: davem; +Cc: yoshfuji, pekkas, netdev
In-Reply-To: <20071210150910.440970057@ICON-9-164-138-215.megacenter.de.ibm.com>

[-- Attachment #1: make-ip6-frag-init-return-an-error.patch --]
[-- Type: text/plain, Size: 2649 bytes --]

This patch makes the frag_init to return an error code, so the af_inet6
module can handle the error.

Signed-off-by: Daniel Lezcano <dlezcano@fr.ibm.com>
---
 include/net/transp_v6.h |    3 ++-
 net/ipv6/af_inet6.c     |    8 ++++++--
 net/ipv6/reassembly.c   |   16 +++++++++++++---
 3 files changed, 21 insertions(+), 6 deletions(-)

Index: net-2.6.25/include/net/transp_v6.h
===================================================================
--- net-2.6.25.orig/include/net/transp_v6.h
+++ net-2.6.25/include/net/transp_v6.h
@@ -19,7 +19,8 @@ struct flowi;
 /* extention headers */
 extern int				ipv6_exthdrs_init(void);
 extern void				ipv6_exthdrs_exit(void);
-extern void				ipv6_frag_init(void);
+extern int				ipv6_frag_init(void);
+extern void				ipv6_frag_exit(void);
 
 /* transport protocols */
 extern void				rawv6_init(void);
Index: net-2.6.25/net/ipv6/af_inet6.c
===================================================================
--- net-2.6.25.orig/net/ipv6/af_inet6.c
+++ net-2.6.25/net/ipv6/af_inet6.c
@@ -863,7 +863,9 @@ static int __init inet6_init(void)
 	if (err)
 		goto ipv6_exthdrs_fail;
 
-	ipv6_frag_init();
+	err = ipv6_frag_init();
+	if (err)
+		goto ipv6_frag_fail;
 
 	/* Init v6 transport protocols. */
 	udpv6_init();
@@ -875,6 +877,8 @@ static int __init inet6_init(void)
 out:
 	return err;
 
+ipv6_frag_fail:
+	ipv6_exthdrs_exit();
 ipv6_exthdrs_fail:
 	addrconf_cleanup();
 addrconf_fail:
@@ -934,7 +938,7 @@ static void __exit inet6_exit(void)
 
 	/* Cleanup code parts. */
 	ipv6_packet_cleanup();
-
+	ipv6_frag_exit();
 	ipv6_exthdrs_exit();
 	addrconf_cleanup();
 	ip6_flowlabel_cleanup();
Index: net-2.6.25/net/ipv6/reassembly.c
===================================================================
--- net-2.6.25.orig/net/ipv6/reassembly.c
+++ net-2.6.25/net/ipv6/reassembly.c
@@ -632,11 +632,13 @@ static struct inet6_protocol frag_protoc
 	.flags		=	INET6_PROTO_NOPOLICY,
 };
 
-void __init ipv6_frag_init(void)
+int __init ipv6_frag_init(void)
 {
-	if (inet6_add_protocol(&frag_protocol, IPPROTO_FRAGMENT) < 0)
-		printk(KERN_ERR "ipv6_frag_init: Could not register protocol\n");
+	int ret;
 
+	ret = inet6_add_protocol(&frag_protocol, IPPROTO_FRAGMENT);
+	if (ret)
+		goto out;
 	ip6_frags.ctl = &ip6_frags_ctl;
 	ip6_frags.hashfn = ip6_hashfn;
 	ip6_frags.constructor = ip6_frag_init;
@@ -646,4 +648,12 @@ void __init ipv6_frag_init(void)
 	ip6_frags.match = ip6_frag_match;
 	ip6_frags.frag_expire = ip6_frag_expire;
 	inet_frags_init(&ip6_frags);
+out:
+	return ret;
+}
+
+void ipv6_frag_exit(void)
+{
+	inet_frags_fini(&ip6_frags);
+	inet6_del_protocol(&frag_protocol, IPPROTO_FRAGMENT);
 }

-- 

^ permalink raw reply

* [patch 1/5] ipv6:  make flowlabel to return an error
From: Daniel Lezcano @ 2007-12-10 15:09 UTC (permalink / raw)
  To: davem; +Cc: yoshfuji, pekkas, netdev
In-Reply-To: <20071210150910.440970057@ICON-9-164-138-215.megacenter.de.ibm.com>

[-- Attachment #1: make-ip6-flowlabel-init-return-an-error-code.patch --]
[-- Type: text/plain, Size: 2837 bytes --]

This patch makes the flowlab subsystem to return an error code and makes
some cleanup with procfs ifdefs.
The af_inet6 will use the flowlabel init return code to check the initialization
was correct.

Signed-off-by: Daniel Lezcano <dlezcano@fr.ibm.com>
---
 include/net/ipv6.h       |    2 +-
 net/ipv6/af_inet6.c      |    5 ++++-
 net/ipv6/ip6_flowlabel.c |   30 +++++++++++++++++++++++-------
 3 files changed, 28 insertions(+), 9 deletions(-)

Index: net-2.6.25/include/net/ipv6.h
===================================================================
--- net-2.6.25.orig/include/net/ipv6.h
+++ net-2.6.25/include/net/ipv6.h
@@ -219,7 +219,7 @@ extern struct ipv6_txoptions	*fl6_merge_
 						   struct ipv6_txoptions * fopt);
 extern void			fl6_free_socklist(struct sock *sk);
 extern int			ipv6_flowlabel_opt(struct sock *sk, char __user *optval, int optlen);
-extern void			ip6_flowlabel_init(void);
+extern int			ip6_flowlabel_init(void);
 extern void			ip6_flowlabel_cleanup(void);
 
 static inline void fl6_sock_release(struct ip6_flowlabel *fl)
Index: net-2.6.25/net/ipv6/af_inet6.c
===================================================================
--- net-2.6.25.orig/net/ipv6/af_inet6.c
+++ net-2.6.25/net/ipv6/af_inet6.c
@@ -851,7 +851,9 @@ static int __init inet6_init(void)
 	err = ip6_route_init();
 	if (err)
 		goto ip6_route_fail;
-	ip6_flowlabel_init();
+	err = ip6_flowlabel_init();
+	if (err)
+		goto ip6_flowlabel_fail;
 	err = addrconf_init();
 	if (err)
 		goto addrconf_fail;
@@ -874,6 +876,7 @@ out:
 
 addrconf_fail:
 	ip6_flowlabel_cleanup();
+ip6_flowlabel_fail:
 	ip6_route_cleanup();
 ip6_route_fail:
 #ifdef CONFIG_PROC_FS
Index: net-2.6.25/net/ipv6/ip6_flowlabel.c
===================================================================
--- net-2.6.25.orig/net/ipv6/ip6_flowlabel.c
+++ net-2.6.25/net/ipv6/ip6_flowlabel.c
@@ -692,20 +692,36 @@ static const struct file_operations ip6f
 	.llseek		=	seq_lseek,
 	.release	=	seq_release_private,
 };
-#endif
 
+static int ip6_flowlabel_proc_init(struct net *net)
+{
+	if (!proc_net_fops_create(net, "ip6_flowlabel", S_IRUGO, &ip6fl_seq_fops))
+		return -ENOMEM;
+	return 0;
+}
 
-void ip6_flowlabel_init(void)
+static void ip6_flowlabel_proc_fini(struct net *net)
 {
-#ifdef CONFIG_PROC_FS
-	proc_net_fops_create(&init_net, "ip6_flowlabel", S_IRUGO, &ip6fl_seq_fops);
+	proc_net_remove(net, "ip6_flowlabel");
+}
+#else
+static inline int ip6_flowlabel_proc_init(struct net *net)
+{
+	return 0;
+}
+static inline void ip6_flowlabel_proc_fini(struct net *net)
+{
+	return ;
+}
 #endif
+
+int ip6_flowlabel_init(void)
+{
+	return ip6_flowlabel_proc_init(&init_net);
 }
 
 void ip6_flowlabel_cleanup(void)
 {
 	del_timer(&ip6_fl_gc_timer);
-#ifdef CONFIG_PROC_FS
-	proc_net_remove(&init_net, "ip6_flowlabel");
-#endif
+	ip6_flowlabel_proc_fini(&init_net);
 }

-- 

^ permalink raw reply

* [patch 5/5] ipv6:  make the protocol initialization to return an error code
From: Daniel Lezcano @ 2007-12-10 15:09 UTC (permalink / raw)
  To: davem; +Cc: yoshfuji, pekkas, netdev
In-Reply-To: <20071210150910.440970057@ICON-9-164-138-215.megacenter.de.ibm.com>

[-- Attachment #1: make-protocol-init-to-return-an-error-code.patch --]
[-- Type: text/plain, Size: 11326 bytes --]

This patchset makes the different protocols to return an error code, so
the af_inet6 module can check the initialization was correct or not.

The raw6 was taken into account to be consistent with the rest of the
protocols, but the registration is at the same place.
Because the raw6 has its own init function, the proto and the ops structure
can be moved inside the raw6.c file.

Signed-off-by: Daniel Lezcano <dlezcano@fr.ibm.com>
---
 include/net/ipv6.h       |    2 -
 include/net/transp_v6.h  |   12 ++++---
 net/ipv6/af_inet6.c      |   77 ++++++++++++++++++++---------------------------
 net/ipv6/ipv6_sockglue.c |    3 +
 net/ipv6/raw.c           |   52 +++++++++++++++++++++++++++++++
 net/ipv6/tcp_ipv6.c      |   38 ++++++++++++++++++-----
 net/ipv6/udp.c           |   26 +++++++++++++--
 net/ipv6/udplite.c       |   25 ++++++++++++---
 8 files changed, 169 insertions(+), 66 deletions(-)

Index: net-2.6.25/include/net/transp_v6.h
===================================================================
--- net-2.6.25.orig/include/net/transp_v6.h
+++ net-2.6.25/include/net/transp_v6.h
@@ -23,10 +23,14 @@ extern int				ipv6_frag_init(void);
 extern void				ipv6_frag_exit(void);
 
 /* transport protocols */
-extern void				rawv6_init(void);
-extern void				udpv6_init(void);
-extern void 				udplitev6_init(void);
-extern void				tcpv6_init(void);
+extern int				rawv6_init(void);
+extern void				rawv6_exit(void);
+extern int				udpv6_init(void);
+extern void				udpv6_exit(void);
+extern int 				udplitev6_init(void);
+extern void 				udplitev6_exit(void);
+extern int				tcpv6_init(void);
+extern void				tcpv6_exit(void);
 
 extern int				udpv6_connect(struct sock *sk,
 						      struct sockaddr *uaddr,
Index: net-2.6.25/net/ipv6/af_inet6.c
===================================================================
--- net-2.6.25.orig/net/ipv6/af_inet6.c
+++ net-2.6.25/net/ipv6/af_inet6.c
@@ -529,42 +529,6 @@ static struct net_proto_family inet6_fam
 	.owner	= THIS_MODULE,
 };
 
-/* Same as inet6_dgram_ops, sans udp_poll.  */
-static const struct proto_ops inet6_sockraw_ops = {
-	.family		   = PF_INET6,
-	.owner		   = THIS_MODULE,
-	.release	   = inet6_release,
-	.bind		   = inet6_bind,
-	.connect	   = inet_dgram_connect,	/* ok		*/
-	.socketpair	   = sock_no_socketpair,	/* a do nothing	*/
-	.accept		   = sock_no_accept,		/* a do nothing	*/
-	.getname	   = inet6_getname,
-	.poll		   = datagram_poll,		/* ok		*/
-	.ioctl		   = inet6_ioctl,		/* must change  */
-	.listen		   = sock_no_listen,		/* ok		*/
-	.shutdown	   = inet_shutdown,		/* ok		*/
-	.setsockopt	   = sock_common_setsockopt,	/* ok		*/
-	.getsockopt	   = sock_common_getsockopt,	/* ok		*/
-	.sendmsg	   = inet_sendmsg,		/* ok		*/
-	.recvmsg	   = sock_common_recvmsg,	/* ok		*/
-	.mmap		   = sock_no_mmap,
-	.sendpage	   = sock_no_sendpage,
-#ifdef CONFIG_COMPAT
-	.compat_setsockopt = compat_sock_common_setsockopt,
-	.compat_getsockopt = compat_sock_common_getsockopt,
-#endif
-};
-
-static struct inet_protosw rawv6_protosw = {
-	.type		= SOCK_RAW,
-	.protocol	= IPPROTO_IP,	/* wild card */
-	.prot		= &rawv6_prot,
-	.ops		= &inet6_sockraw_ops,
-	.capability	= CAP_NET_RAW,
-	.no_check	= UDP_CSUM_DEFAULT,
-	.flags		= INET_PROTOSW_REUSE,
-};
-
 int inet6_register_protosw(struct inet_protosw *p)
 {
 	struct list_head *lh;
@@ -771,7 +735,6 @@ static int __init inet6_init(void)
 	__this_module.can_unload = &ipv6_unload;
 #endif
 #endif
-
 	err = proto_register(&tcpv6_prot, 1);
 	if (err)
 		goto out;
@@ -796,14 +759,16 @@ static int __init inet6_init(void)
 	/* We MUST register RAW sockets before we create the ICMP6,
 	 * IGMP6, or NDISC control sockets.
 	 */
-	inet6_register_protosw(&rawv6_protosw);
+	err = rawv6_init();
+	if (err)
+		goto out_unregister_raw_proto;
 
 	/* Register the family here so that the init calls below will
 	 * be able to create sockets. (?? is this dangerous ??)
 	 */
 	err = sock_register(&inet6_family_ops);
 	if (err)
-		goto out_unregister_raw_proto;
+		goto out_sock_register_fail;
 
 	/* Initialise ipv6 mibs */
 	err = init_ipv6_mibs();
@@ -871,15 +836,32 @@ static int __init inet6_init(void)
 		goto ipv6_frag_fail;
 
 	/* Init v6 transport protocols. */
-	udpv6_init();
-	udplitev6_init();
-	tcpv6_init();
+	err = udpv6_init();
+	if (err)
+		goto udpv6_fail;
+
+	err = udplitev6_init();
+	if (err)
+		goto udplitev6_fail;
+
+	err = tcpv6_init();
+	if (err)
+		goto tcpv6_fail;
 
-	ipv6_packet_init();
-	err = 0;
+	err = ipv6_packet_init();
+	if (err)
+		goto ipv6_packet_fail;
 out:
 	return err;
 
+ipv6_packet_fail:
+	tcpv6_exit();
+tcpv6_fail:
+	udplitev6_exit();
+udplitev6_fail:
+	udpv6_exit();
+udpv6_fail:
+	ipv6_frag_exit();
 ipv6_frag_fail:
 	ipv6_exthdrs_exit();
 ipv6_exthdrs_fail:
@@ -920,6 +902,8 @@ icmp_fail:
 out_unregister_sock:
 	sock_unregister(PF_INET6);
 	rtnl_unregister_all(PF_INET6);
+out_sock_register_fail:
+	rawv6_exit();
 out_unregister_raw_proto:
 	proto_unregister(&rawv6_prot);
 out_unregister_udplite_proto:
@@ -939,6 +923,10 @@ static void __exit inet6_exit(void)
 	/* Disallow any further netlink messages */
 	rtnl_unregister_all(PF_INET6);
 
+	udpv6_exit();
+	udplitev6_exit();
+	tcpv6_exit();
+
 	/* Cleanup code parts. */
 	ipv6_packet_cleanup();
 	ipv6_frag_exit();
@@ -961,6 +949,7 @@ static void __exit inet6_exit(void)
 	igmp6_cleanup();
 	ndisc_cleanup();
 	icmpv6_cleanup();
+	rawv6_exit();
 #ifdef CONFIG_SYSCTL
 	ipv6_sysctl_unregister();
 #endif
Index: net-2.6.25/net/ipv6/udp.c
===================================================================
--- net-2.6.25.orig/net/ipv6/udp.c
+++ net-2.6.25/net/ipv6/udp.c
@@ -1016,9 +1016,27 @@ static struct inet_protosw udpv6_protosw
 };
 
 
-void __init udpv6_init(void)
+int __init udpv6_init(void)
 {
-	if (inet6_add_protocol(&udpv6_protocol, IPPROTO_UDP) < 0)
-		printk(KERN_ERR "udpv6_init: Could not register protocol\n");
-	inet6_register_protosw(&udpv6_protosw);
+	int ret;
+
+	ret = inet6_add_protocol(&udpv6_protocol, IPPROTO_UDP);
+	if (ret)
+		goto out;
+
+	ret = inet6_register_protosw(&udpv6_protosw);
+	if (ret)
+		goto out_udpv6_protocol;
+out:
+	return ret;
+
+out_udpv6_protocol:
+	inet6_del_protocol(&udpv6_protocol, IPPROTO_UDP);
+	goto out;
+}
+
+void __exit udpv6_exit(void)
+{
+	inet6_unregister_protosw(&udpv6_protosw);
+	inet6_del_protocol(&udpv6_protocol, IPPROTO_UDP);
 }
Index: net-2.6.25/include/net/ipv6.h
===================================================================
--- net-2.6.25.orig/include/net/ipv6.h
+++ net-2.6.25/include/net/ipv6.h
@@ -545,7 +545,7 @@ extern int			compat_ipv6_getsockopt(stru
 						char __user *optval,
 						int __user *optlen);
 
-extern void			ipv6_packet_init(void);
+extern int			ipv6_packet_init(void);
 
 extern void			ipv6_packet_cleanup(void);
 
Index: net-2.6.25/net/ipv6/ipv6_sockglue.c
===================================================================
--- net-2.6.25.orig/net/ipv6/ipv6_sockglue.c
+++ net-2.6.25/net/ipv6/ipv6_sockglue.c
@@ -1130,9 +1130,10 @@ int compat_ipv6_getsockopt(struct sock *
 EXPORT_SYMBOL(compat_ipv6_getsockopt);
 #endif
 
-void __init ipv6_packet_init(void)
+int __init ipv6_packet_init(void)
 {
 	dev_add_pack(&ipv6_packet_type);
+	return 0;
 }
 
 void ipv6_packet_cleanup(void)
Index: net-2.6.25/net/ipv6/raw.c
===================================================================
--- net-2.6.25.orig/net/ipv6/raw.c
+++ net-2.6.25/net/ipv6/raw.c
@@ -1273,3 +1273,55 @@ void raw6_proc_exit(void)
 	proc_net_remove(&init_net, "raw6");
 }
 #endif	/* CONFIG_PROC_FS */
+
+/* Same as inet6_dgram_ops, sans udp_poll.  */
+static const struct proto_ops inet6_sockraw_ops = {
+	.family		   = PF_INET6,
+	.owner		   = THIS_MODULE,
+	.release	   = inet6_release,
+	.bind		   = inet6_bind,
+	.connect	   = inet_dgram_connect,	/* ok		*/
+	.socketpair	   = sock_no_socketpair,	/* a do nothing	*/
+	.accept		   = sock_no_accept,		/* a do nothing	*/
+	.getname	   = inet6_getname,
+	.poll		   = datagram_poll,		/* ok		*/
+	.ioctl		   = inet6_ioctl,		/* must change  */
+	.listen		   = sock_no_listen,		/* ok		*/
+	.shutdown	   = inet_shutdown,		/* ok		*/
+	.setsockopt	   = sock_common_setsockopt,	/* ok		*/
+	.getsockopt	   = sock_common_getsockopt,	/* ok		*/
+	.sendmsg	   = inet_sendmsg,		/* ok		*/
+	.recvmsg	   = sock_common_recvmsg,	/* ok		*/
+	.mmap		   = sock_no_mmap,
+	.sendpage	   = sock_no_sendpage,
+#ifdef CONFIG_COMPAT
+	.compat_setsockopt = compat_sock_common_setsockopt,
+	.compat_getsockopt = compat_sock_common_getsockopt,
+#endif
+};
+
+static struct inet_protosw rawv6_protosw = {
+	.type		= SOCK_RAW,
+	.protocol	= IPPROTO_IP,	/* wild card */
+	.prot		= &rawv6_prot,
+	.ops		= &inet6_sockraw_ops,
+	.capability	= CAP_NET_RAW,
+	.no_check	= UDP_CSUM_DEFAULT,
+	.flags		= INET_PROTOSW_REUSE,
+};
+
+int __init rawv6_init(void)
+{
+	int ret;
+
+	ret = inet6_register_protosw(&rawv6_protosw);
+	if (ret)
+		goto out;
+out:
+	return ret;
+}
+
+void __exit rawv6_exit(void)
+{
+	inet6_unregister_protosw(&rawv6_protosw);
+}
Index: net-2.6.25/net/ipv6/tcp_ipv6.c
===================================================================
--- net-2.6.25.orig/net/ipv6/tcp_ipv6.c
+++ net-2.6.25/net/ipv6/tcp_ipv6.c
@@ -2167,14 +2167,36 @@ static struct inet_protosw tcpv6_protosw
 				INET_PROTOSW_ICSK,
 };
 
-void __init tcpv6_init(void)
+int __init tcpv6_init(void)
 {
+	int ret;
+
+	ret = inet6_add_protocol(&tcpv6_protocol, IPPROTO_TCP);
+	if (ret)
+		goto out;
+
 	/* register inet6 protocol */
-	if (inet6_add_protocol(&tcpv6_protocol, IPPROTO_TCP) < 0)
-		printk(KERN_ERR "tcpv6_init: Could not register protocol\n");
-	inet6_register_protosw(&tcpv6_protosw);
-
-	if (inet_csk_ctl_sock_create(&tcp6_socket, PF_INET6, SOCK_RAW,
-				     IPPROTO_TCP) < 0)
-		panic("Failed to create the TCPv6 control socket.\n");
+	ret = inet6_register_protosw(&tcpv6_protosw);
+	if (ret)
+		goto out_tcpv6_protocol;
+
+	ret = inet_csk_ctl_sock_create(&tcp6_socket, PF_INET6,
+				       SOCK_RAW, IPPROTO_TCP);
+	if (ret)
+		goto out_tcpv6_protosw;
+out:
+	return ret;
+
+out_tcpv6_protocol:
+	inet6_del_protocol(&tcpv6_protocol, IPPROTO_TCP);
+out_tcpv6_protosw:
+	inet6_unregister_protosw(&tcpv6_protosw);
+	goto out;
+}
+
+void __exit tcpv6_exit(void)
+{
+	sock_release(tcp6_socket);
+	inet6_unregister_protosw(&tcpv6_protosw);
+	inet6_del_protocol(&tcpv6_protocol, IPPROTO_TCP);
 }
Index: net-2.6.25/net/ipv6/udplite.c
===================================================================
--- net-2.6.25.orig/net/ipv6/udplite.c
+++ net-2.6.25/net/ipv6/udplite.c
@@ -77,12 +77,29 @@ static struct inet_protosw udplite6_prot
 	.flags		= INET_PROTOSW_PERMANENT,
 };
 
-void __init udplitev6_init(void)
+int __init udplitev6_init(void)
 {
-	if (inet6_add_protocol(&udplitev6_protocol, IPPROTO_UDPLITE) < 0)
-		printk(KERN_ERR "%s: Could not register.\n", __FUNCTION__);
+	int ret;
 
-	inet6_register_protosw(&udplite6_protosw);
+	ret = inet6_add_protocol(&udplitev6_protocol, IPPROTO_UDPLITE);
+	if (ret)
+		goto out;
+
+	ret = inet6_register_protosw(&udplite6_protosw);
+	if (ret)
+		goto out_udplitev6_protocol;
+out:
+	return ret;
+
+out_udplitev6_protocol:
+	inet6_del_protocol(&udplitev6_protocol, IPPROTO_UDPLITE);
+	goto out;
+}
+
+void __exit udplitev6_exit(void)
+{
+	inet6_unregister_protosw(&udplite6_protosw);
+	inet6_del_protocol(&udplitev6_protocol, IPPROTO_UDPLITE);
 }
 
 #ifdef CONFIG_PROC_FS

-- 

^ permalink raw reply

* [patch 2/5] ipv6:  make extended headers to return an error at initialization
From: Daniel Lezcano @ 2007-12-10 15:09 UTC (permalink / raw)
  To: davem; +Cc: yoshfuji, pekkas, netdev
In-Reply-To: <20071210150910.440970057@ICON-9-164-138-215.megacenter.de.ibm.com>

[-- Attachment #1: make-ip6-exthdrs-init-return-an-error.patch --]
[-- Type: text/plain, Size: 4320 bytes --]

This patch factorize the code for the differents init functions for rthdr,
nodata, destopt in a single function exthdrs_init.
This function returns an error so the af_inet6 module can check correctly
the initialization.

Signed-off-by: Daniel Lezcano <dlezcano@fr.ibm.com>
---
 include/net/transp_v6.h |    5 +--
 net/ipv6/af_inet6.c     |   10 +++++--
 net/ipv6/exthdrs.c      |   64 +++++++++++++++++++++++++++++-------------------
 3 files changed, 48 insertions(+), 31 deletions(-)

Index: net-2.6.25/include/net/transp_v6.h
===================================================================
--- net-2.6.25.orig/include/net/transp_v6.h
+++ net-2.6.25/include/net/transp_v6.h
@@ -17,10 +17,9 @@ extern struct proto tcpv6_prot;
 struct flowi;
 
 /* extention headers */
-extern void				ipv6_rthdr_init(void);
+extern int				ipv6_exthdrs_init(void);
+extern void				ipv6_exthdrs_exit(void);
 extern void				ipv6_frag_init(void);
-extern void				ipv6_nodata_init(void);
-extern void				ipv6_destopt_init(void);
 
 /* transport protocols */
 extern void				rawv6_init(void);
Index: net-2.6.25/net/ipv6/af_inet6.c
===================================================================
--- net-2.6.25.orig/net/ipv6/af_inet6.c
+++ net-2.6.25/net/ipv6/af_inet6.c
@@ -859,10 +859,11 @@ static int __init inet6_init(void)
 		goto addrconf_fail;
 
 	/* Init v6 extension headers. */
-	ipv6_rthdr_init();
+	err = ipv6_exthdrs_init();
+	if (err)
+		goto ipv6_exthdrs_fail;
+
 	ipv6_frag_init();
-	ipv6_nodata_init();
-	ipv6_destopt_init();
 
 	/* Init v6 transport protocols. */
 	udpv6_init();
@@ -874,6 +875,8 @@ static int __init inet6_init(void)
 out:
 	return err;
 
+ipv6_exthdrs_fail:
+	addrconf_cleanup();
 addrconf_fail:
 	ip6_flowlabel_cleanup();
 ip6_flowlabel_fail:
@@ -932,6 +935,7 @@ static void __exit inet6_exit(void)
 	/* Cleanup code parts. */
 	ipv6_packet_cleanup();
 
+	ipv6_exthdrs_exit();
 	addrconf_cleanup();
 	ip6_flowlabel_cleanup();
 	ip6_route_cleanup();
Index: net-2.6.25/net/ipv6/exthdrs.c
===================================================================
--- net-2.6.25.orig/net/ipv6/exthdrs.c
+++ net-2.6.25/net/ipv6/exthdrs.c
@@ -308,28 +308,6 @@ static int ipv6_destopt_rcv(struct sk_bu
 	return -1;
 }
 
-static struct inet6_protocol destopt_protocol = {
-	.handler	=	ipv6_destopt_rcv,
-	.flags		=	INET6_PROTO_NOPOLICY | INET6_PROTO_GSO_EXTHDR,
-};
-
-void __init ipv6_destopt_init(void)
-{
-	if (inet6_add_protocol(&destopt_protocol, IPPROTO_DSTOPTS) < 0)
-		printk(KERN_ERR "ipv6_destopt_init: Could not register protocol\n");
-}
-
-static struct inet6_protocol nodata_protocol = {
-	.handler	=	dst_discard,
-	.flags		=	INET6_PROTO_NOPOLICY,
-};
-
-void __init ipv6_nodata_init(void)
-{
-	if (inet6_add_protocol(&nodata_protocol, IPPROTO_NONE) < 0)
-		printk(KERN_ERR "ipv6_nodata_init: Could not register protocol\n");
-}
-
 /********************************
   Routing header.
  ********************************/
@@ -527,12 +505,48 @@ static struct inet6_protocol rthdr_proto
 	.flags		=	INET6_PROTO_NOPOLICY | INET6_PROTO_GSO_EXTHDR,
 };
 
-void __init ipv6_rthdr_init(void)
+static struct inet6_protocol destopt_protocol = {
+	.handler	=	ipv6_destopt_rcv,
+	.flags		=	INET6_PROTO_NOPOLICY | INET6_PROTO_GSO_EXTHDR,
+};
+
+static struct inet6_protocol nodata_protocol = {
+	.handler	=	dst_discard,
+	.flags		=	INET6_PROTO_NOPOLICY,
+};
+
+int __init ipv6_exthdrs_init(void)
 {
-	if (inet6_add_protocol(&rthdr_protocol, IPPROTO_ROUTING) < 0)
-		printk(KERN_ERR "ipv6_rthdr_init: Could not register protocol\n");
+	int ret;
+
+	ret = inet6_add_protocol(&rthdr_protocol, IPPROTO_ROUTING);
+	if (ret)
+		goto out;
+
+	ret = inet6_add_protocol(&destopt_protocol, IPPROTO_DSTOPTS);
+	if (ret)
+		goto out_rthdr;
+
+	ret = inet6_add_protocol(&nodata_protocol, IPPROTO_NONE);
+	if (ret)
+		goto out_destopt;
+
+out:
+	return ret;
+out_rthdr:
+	inet6_del_protocol(&rthdr_protocol, IPPROTO_ROUTING);
+out_destopt:
+	inet6_del_protocol(&destopt_protocol, IPPROTO_DSTOPTS);
+	goto out;
 };
 
+void ipv6_exthdrs_exit(void)
+{
+	inet6_del_protocol(&nodata_protocol, IPPROTO_NONE);
+	inet6_del_protocol(&destopt_protocol, IPPROTO_DSTOPTS);
+	inet6_del_protocol(&rthdr_protocol, IPPROTO_ROUTING);
+}
+
 /**********************************
   Hop-by-hop options.
  **********************************/

-- 

^ permalink raw reply

* [patch 0/5] ipv6:  make af_inet6 subsystems to return an error at init
From: Daniel Lezcano @ 2007-12-10 15:09 UTC (permalink / raw)
  To: davem; +Cc: yoshfuji, pekkas, netdev

This patchset continue the work to make the different af_inet6 
subsystems initialization functions to return an error code and
to handle the error to fails safely.

It takes into account:
	* flowlabel
	* exthdrs
	* frag
	* udp
	* udplite
	* tcp
	* raw
-- 

^ permalink raw reply

* Re: [1/4] DST: Distributed storage documentation.
From: Evgeniy Polyakov @ 2007-12-10 15:12 UTC (permalink / raw)
  To: Kay Sievers; +Cc: lkml, netdev, linux-fsdevel, Greg KH
In-Reply-To: <20071210145055.GB7184@2ka.mipt.ru>

On Mon, Dec 10, 2007 at 05:50:55PM +0300, Evgeniy Polyakov (johnpol@2ka.mipt.ru) wrote:
> > Further questions:
> > Why do you do your own refcounting instead of using kref?
> 
> That's because I always used atomic operations as a reference counters
> and did not tried krefs :)
> They are the same actually (module tricky arches where smp_mb_* are
> required), so I can replace them in the next release.

Actually not - I have to set reference counter to something other than 1
or +/- 1, and thus will have to call kref_get() in a loop, which is a
very ugly step. Is there kref_set() or somethinglike that? At least not
in 2.6.22 what I'm using for now.

Sigh, I've converted most of the DST already...

-- 
	Evgeniy Polyakov

^ permalink raw reply

* RE: routing policy based on u32 classifier
From: Brian S Julin @ 2007-12-10 14:57 UTC (permalink / raw)
  To: Marco Berizzi, netdev@vger.kernel.org
In-Reply-To: <BAY103-DAV51710C05B584C53DED66DB26B0@phx.gbl>



Marco wrote:

> Hello everybody.
> Kindly, I would like to know if the is any plan to add this feature to a future kernel release.
> I know that fwmark is able to do this, but there is the limitation in source ip address selection.

Could you explain the limitation?  My iptables manpage seems to suggest
that u32 is pretty general.  Are you just asking if the pom-ng ipt_u32
will be mainlined?


^ permalink raw reply

* Re: [1/4] DST: Distributed storage documentation.
From: Evgeniy Polyakov @ 2007-12-10 14:50 UTC (permalink / raw)
  To: Kay Sievers; +Cc: lkml, netdev, linux-fsdevel, Greg KH
In-Reply-To: <1197297108.6399.91.camel@lov.site>

On Mon, Dec 10, 2007 at 03:31:48PM +0100, Kay Sievers (kay.sievers@vrfy.org) wrote:
> > I meant that for each new device, it will be placed into
> > /sys/devices/its_name, but it can also be accessed via
> > /sys/bus/dst/devices/
> 
> Still, it looks like a path. :)
> 
> Please don't reference any device directly with a /sys/devices/ path.
> You have to use the subsystem links to the devices
> in /sys/bus/dst/devices/. Devices are free to move around
> in /sys/devices, even during runtime. Yours don't do, but anyway, please
> remove all mentioning of direct access to /sys/devices/.

Ok, I will update documentation to reference /sys/bus/dst/devices
instead of /sys/devices

> Btw, where is the top-level /sys/devices/storage/ coming from? I don't
> see that in the code. We don't accept any new "virtual parents" here.
>
> Your devices will automatically appear in /sys/devices/virtual/dst/, and
> not below your own parent. But that path does not matter anyway, because
> you should only access them from the /sys/bus/dst/devices/ directory.
> 
> And in general please don't claim generic names like "storage" in any
> namespace for a very specific subsystem like this.

It is not a parent - it is an example for device called 'storage', if it
will be called 'testing', then path will be /sys/devices/testing or more
correct /sys/bus/dst/devices/testing :)

> > It is 'dst' bus.
> > 
> > uganda:~/codes# ls -la /sys/devices/staorge/
> > total 0
> > drwxr-xr-x 4 root root    0 2007-12-10 11:46 .
> > drwxr-xr-x 9 root root    0 2007-12-10 11:46 ..
> > -r--r--r-- 1 root root 4096 2007-12-10 11:46 alg
> > lrwxrwxrwx 1 root root    0 2007-12-10 11:46 bus -> ../../bus/dst
> > drwxr-xr-x 3 root root    0 2007-12-10 11:46 n-0-ffff81003e24117
> > -r--r--r-- 1 root root 4096 2007-12-10 11:46 name
> > -r--r--r-- 1 root root 4096 2007-12-10 11:46 nodes
> > drwxr-xr-x 2 root root    0 2007-12-10 11:46 power
> > -rw-r--r-- 1 root root 4096 2007-12-10 11:46 remove_all_nodes
> > lrwxrwxrwx 1 root root    0 2007-12-10 11:46 subsystem -> ../../bus/dst
> > -rw-r--r-- 1 root root 4096 2007-12-10 11:46 uevent
> 
> Ok, how does:
>   ls -l /sys/devices/storage/n-0-ffff81003e24117
> look?

uganda:~/codes# ls -l /sys/devices/storage/n-0-ffff81003ebc220/
total 0
drwxr-xr-x 2 root root    0 2007-12-10 13:23 power
-r--r--r-- 1 root root 4096 2007-12-10 13:30 size
-r--r--r-- 1 root root 4096 2007-12-10 13:30 start
-r--r--r-- 1 root root 4096 2007-12-10 13:30 type
-rw-r--r-- 1 root root 4096 2007-12-10 13:30 uevent


> > uganda:~/codes# ls -l /sys/bus/dst/
> > total 0
> > drwxr-xr-x 2 root root    0 2007-12-10 09:52 devices
> > drwxr-xr-x 2 root root    0 2007-12-10 09:52 drivers
> > -rw-r--r-- 1 root root 4096 2007-12-10 11:46 drivers_autoprobe
> > --w------- 1 root root 4096 2007-12-10 11:46 drivers_probe
> 
> How does:
>   ls -l /sys/bus/dst/devices
> look?

uganda:~/codes# ls -la /sys/bus/dst/devices/
total 0
drwxr-xr-x 2 root root 0 2007-12-10 13:30 .
drwxr-xr-x 4 root root 0 2007-12-10 13:22 ..
lrwxrwxrwx 1 root root 0 2007-12-10 13:30 storage -> ../../../devices/storage


Here 'storage' is just a name for device called 'storage', it can be
anything else.
 
> Further questions:
> Why do you do your own refcounting instead of using kref?

That's because I always used atomic operations as a reference counters
and did not tried krefs :)
They are the same actually (module tricky arches where smp_mb_* are
required), so I can replace them in the next release.

> Why don't you use groups for the attributes?

For 3-4 attributes it is faster to register them in a loop than typing
another structure :)

> Why don't you use default attributes for the device, where you get all
> error handling done by the core.

What is 'default attributes' and for what devices?
All my sysfs files are so much trivial, so they do not need anything
special and I do not see what is error handling you mentioned.

-- 
	Evgeniy Polyakov

^ permalink raw reply

* Re: [PATCH 0/2] netem: trace enhancement
From: Ariane Keller @ 2007-12-10 14:32 UTC (permalink / raw)
  To: Patrick McHardy
  Cc: Ariane Keller, Ben Greear, Stephen Hemminger, netdev, herbert,
	Rainer Baumann
In-Reply-To: <4756A213.2060806@trash.net>

I finally managed to rewrite the netem trace extension to use rtnetlink 
communication for the data transfer for user space to kernel space.

The kernel patch is available here:
http://www.tcn.hypert.net/tcn_kernel_2_6_23_rtnetlink

and the iproute patch is here:
http://www.tcn.hypert.net/tcn_iproute2_2_6_23_rtnetlink

Whenever new data is needed the kernel module sends a notification to 
the user space process. Thereupon the user space process sends a data 
package to the kernel module.
I had to write a new qdisc_notify function (qdisc_notify_pid) since the 
other was acquiring a lock, which we already hold in this situation.

I hope everything works as expected and I'm looking forward for your 
comments.

Thanks!
Ariane

^ permalink raw reply

* Re: [1/4] DST: Distributed storage documentation.
From: Kay Sievers @ 2007-12-10 14:31 UTC (permalink / raw)
  To: Evgeniy Polyakov; +Cc: lkml, netdev, linux-fsdevel, Greg KH
In-Reply-To: <20071210125839.GA16789@2ka.mipt.ru>

On Mon, 2007-12-10 at 15:58 +0300, Evgeniy Polyakov wrote:
> On Mon, Dec 10, 2007 at 01:51:43PM +0100, Kay Sievers (kay.sievers@vrfy.org) wrote:
> > On Dec 10, 2007 12:47 PM, Evgeniy Polyakov <johnpol@2ka.mipt.ru> wrote:
> > > diff --git a/Documentation/dst/sysfs.txt b/Documentation/dst/sysfs.txt
> > > new file mode 100644
> > > index 0000000..79d79dc
> > > --- /dev/null
> > > +++ b/Documentation/dst/sysfs.txt
> > > @@ -0,0 +1,30 @@
> > > +This file describes sysfs files created for each storage.
> > > +
> > > +1. Per-storage files.
> > > +Each storage has its own dir /sysfs/devices/$storage_name,
> > 
> > It's always /sys/devices/.
> 
> I meant that for each new device, it will be placed into
> /sys/devices/its_name, but it can also be accessed via
> /sys/bus/dst/devices/

Still, it looks like a path. :)

Please don't reference any device directly with a /sys/devices/ path.
You have to use the subsystem links to the devices
in /sys/bus/dst/devices/. Devices are free to move around
in /sys/devices, even during runtime. Yours don't do, but anyway, please
remove all mentioning of direct access to /sys/devices/.

Btw, where is the top-level /sys/devices/storage/ coming from? I don't
see that in the code. We don't accept any new "virtual parents" here.
Your devices will automatically appear in /sys/devices/virtual/dst/, and
not below your own parent. But that path does not matter anyway, because
you should only access them from the /sys/bus/dst/devices/ directory.

And in general please don't claim generic names like "storage" in any
namespace for a very specific subsystem like this.

> > > +which contains following files:
> > > +
> > > +alg - contains name of the algorithm used to created given storage
> > > +name - name of the storage
> > > +nodes - map of the storage (list of nodes and their sizes and starts)
> > > +remove_all_nodes - writable file which allows to remove all nodes from given
> > > +       storage
> > > +n-$start-$cookie - per node directory, where
> > > +       $start - start of the given node in sectors,
> > > +       $cookie - unique node's id used by DST
> > > +
> > > +2. Per-node files.
> > > +Node's files are located in /sysfs/devices/$storage_name/n-$start-$cookie
> > > +directory, described above.
> > 
> > To which class or bus do the devices you create belong? Care to show a
> > "tree" or "ls -la" of the device?
> 
> It is 'dst' bus.
> 
> uganda:~/codes# ls -la /sys/devices/staorge/
> total 0
> drwxr-xr-x 4 root root    0 2007-12-10 11:46 .
> drwxr-xr-x 9 root root    0 2007-12-10 11:46 ..
> -r--r--r-- 1 root root 4096 2007-12-10 11:46 alg
> lrwxrwxrwx 1 root root    0 2007-12-10 11:46 bus -> ../../bus/dst
> drwxr-xr-x 3 root root    0 2007-12-10 11:46 n-0-ffff81003e24117
> -r--r--r-- 1 root root 4096 2007-12-10 11:46 name
> -r--r--r-- 1 root root 4096 2007-12-10 11:46 nodes
> drwxr-xr-x 2 root root    0 2007-12-10 11:46 power
> -rw-r--r-- 1 root root 4096 2007-12-10 11:46 remove_all_nodes
> lrwxrwxrwx 1 root root    0 2007-12-10 11:46 subsystem -> ../../bus/dst
> -rw-r--r-- 1 root root 4096 2007-12-10 11:46 uevent

Ok, how does:
  ls -l /sys/devices/storage/n-0-ffff81003e24117
look?

> uganda:~/codes# ls -l /sys/bus/dst/
> total 0
> drwxr-xr-x 2 root root    0 2007-12-10 09:52 devices
> drwxr-xr-x 2 root root    0 2007-12-10 09:52 drivers
> -rw-r--r-- 1 root root 4096 2007-12-10 11:46 drivers_autoprobe
> --w------- 1 root root 4096 2007-12-10 11:46 drivers_probe

How does:
  ls -l /sys/bus/dst/devices
look?


Further questions:
Why do you do your own refcounting instead of using kref?
Why don't you use groups for the attributes?
Why don't you use default attributes for the device, where you get all
error handling done by the core.

Kay


^ permalink raw reply

* [PATCH 3/4] [PATCH v2] [TFRC]: Ringbuffer to track loss interval history
From: Gerrit Renker @ 2007-12-10 13:11 UTC (permalink / raw)
  To: acme; +Cc: dccp, netdev, Gerrit Renker
In-Reply-To: <1197292318-29659-3-git-send-email-gerrit@erg.abdn.ac.uk>

A ringbuffer-based implementation of loss interval history is easier to
maintain, allocate, and update.

The `swap' routine to keep the RX history sorted is due to and was written
by Arnaldo Carvalho de Melo, simplifying an earlier macro-based variant.

Details:
 * access to the Loss Interval Records via macro wrappers (with safety checks);
 * simplified, on-demand allocation of entries (no extra memory consumption on
   lossless links); cache allocation is local to the module / exported as service;
 * provision of RFC-compliant algorithm to re-compute average loss interval;
 * provision of comprehensive, new loss detection algorithm
 	- support for all cases of loss, including re-ordered/duplicate packets;
 	- waiting for NDUPACK=3 packets to fill the hole;
	- updating loss records when a late-arriving packet fills a hole.

Signed-off-by: Gerrit Renker <gerrit@erg.abdn.ac.uk>
Signed-off-by: Ian McDonald <ian.mcdonald@jandi.co.nz>
---
 net/dccp/ccids/lib/loss_interval.c  |  161 +++++++++++++++++++++++++++-
 net/dccp/ccids/lib/loss_interval.h  |   56 ++++++++++-
 net/dccp/ccids/lib/packet_history.c |  202 +++++++++++++++++++++++++++++++++++
 net/dccp/ccids/lib/packet_history.h |   11 ++-
 net/dccp/ccids/lib/tfrc.h           |    3 +
 5 files changed, 423 insertions(+), 10 deletions(-)

diff --git a/net/dccp/ccids/lib/loss_interval.c b/net/dccp/ccids/lib/loss_interval.c
index c0a933a..39980d1 100644
--- a/net/dccp/ccids/lib/loss_interval.c
+++ b/net/dccp/ccids/lib/loss_interval.c
@@ -1,6 +1,7 @@
 /*
  *  net/dccp/ccids/lib/loss_interval.c
  *
+ *  Copyright (c) 2007   The University of Aberdeen, Scotland, UK
  *  Copyright (c) 2005-7 The University of Waikato, Hamilton, New Zealand.
  *  Copyright (c) 2005-7 Ian McDonald <ian.mcdonald@jandi.co.nz>
  *  Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
@@ -10,12 +11,7 @@
  *  the Free Software Foundation; either version 2 of the License, or
  *  (at your option) any later version.
  */
-
-#include <linux/module.h>
 #include <net/sock.h>
-#include "../../dccp.h"
-#include "loss_interval.h"
-#include "packet_history.h"
 #include "tfrc.h"
 
 #define DCCP_LI_HIST_IVAL_F_LENGTH  8
@@ -27,6 +23,54 @@ struct dccp_li_hist_entry {
 	u32		 dccplih_interval;
 };
 
+static struct kmem_cache  *tfrc_lh_slab  __read_mostly;
+/* Loss Interval weights from [RFC 3448, 5.4], scaled by 10 */
+static const int tfrc_lh_weights[NINTERVAL] = { 10, 10, 10, 10, 8, 6, 4, 2 };
+
+/* implements LIFO semantics on the array */
+static inline u8 LIH_INDEX(const u8 ctr)
+{
+	return (LIH_SIZE - 1 - (ctr % LIH_SIZE));
+}
+
+/* the `counter' index always points at the next entry to be populated */
+static inline struct tfrc_loss_interval *tfrc_lh_peek(struct tfrc_loss_hist *lh)
+{
+	return lh->counter ? lh->ring[LIH_INDEX(lh->counter - 1)] : NULL;
+}
+
+/* given i with 0 <= i <= k, return I_i as per the rfc3448bis notation */
+static inline u32 tfrc_lh_get_interval(struct tfrc_loss_hist *lh, const u8 i)
+{
+	BUG_ON(i >= lh->counter);
+	return lh->ring[LIH_INDEX(lh->counter - i - 1)]->li_length;
+}
+
+/*
+ *	On-demand allocation and de-allocation of entries
+ */
+static struct tfrc_loss_interval *tfrc_lh_demand_next(struct tfrc_loss_hist *lh)
+{
+	if (lh->ring[LIH_INDEX(lh->counter)] == NULL)
+		lh->ring[LIH_INDEX(lh->counter)] = kmem_cache_alloc(tfrc_lh_slab,
+								    GFP_ATOMIC);
+	return lh->ring[LIH_INDEX(lh->counter)];
+}
+
+void tfrc_lh_cleanup(struct tfrc_loss_hist *lh)
+{
+	if (!tfrc_lh_is_initialised(lh))
+		return;
+
+	for (lh->counter = 0; lh->counter < LIH_SIZE; lh->counter++)
+		if (lh->ring[LIH_INDEX(lh->counter)] != NULL) {
+			kmem_cache_free(tfrc_lh_slab,
+					lh->ring[LIH_INDEX(lh->counter)]);
+			lh->ring[LIH_INDEX(lh->counter)] = NULL;
+		}
+}
+EXPORT_SYMBOL_GPL(tfrc_lh_cleanup);
+
 static struct kmem_cache *dccp_li_cachep __read_mostly;
 
 static inline struct dccp_li_hist_entry *dccp_li_hist_entry_new(const gfp_t prio)
@@ -98,6 +142,65 @@ u32 dccp_li_hist_calc_i_mean(struct list_head *list)
 
 EXPORT_SYMBOL_GPL(dccp_li_hist_calc_i_mean);
 
+static void tfrc_lh_calc_i_mean(struct tfrc_loss_hist *lh)
+{
+	u32 i_i, i_tot0 = 0, i_tot1 = 0, w_tot = 0;
+	int i, k = tfrc_lh_length(lh) - 1; /* k is as in rfc3448bis, 5.4 */
+
+	for (i=0; i <= k; i++) {
+		i_i = tfrc_lh_get_interval(lh, i);
+
+		if (i < k) {
+			i_tot0 += i_i * tfrc_lh_weights[i];
+			w_tot  += tfrc_lh_weights[i];
+		}
+		if (i > 0)
+			i_tot1 += i_i * tfrc_lh_weights[i-1];
+	}
+
+	BUG_ON(w_tot == 0);
+	lh->i_mean = max(i_tot0, i_tot1) / w_tot;
+}
+
+/**
+ * tfrc_lh_update_i_mean  -  Update the `open' loss interval I_0
+ * For recomputing p: returns `true' if p > p_prev  <=>  1/p < 1/p_prev
+ */
+u8 tfrc_lh_update_i_mean(struct tfrc_loss_hist *lh, struct sk_buff *skb)
+{
+	struct tfrc_loss_interval *cur = tfrc_lh_peek(lh);
+	u32 old_i_mean = lh->i_mean;
+	s64 length;
+
+	if (cur == NULL)			/* not initialised */
+		return 0;
+
+	length = dccp_delta_seqno(cur->li_seqno, DCCP_SKB_CB(skb)->dccpd_seq);
+
+	if (length - cur->li_length <= 0)	/* duplicate or reordered */
+		return 0;
+
+	if (SUB16(dccp_hdr(skb)->dccph_ccval, cur->li_ccval) > 4)
+		/*
+		 * Implements RFC 4342, 10.2:
+		 * If a packet S (skb) exists whose seqno comes `after' the one
+		 * starting the current loss interval (cur) and if the modulo-16
+		 * distance from C(cur) to C(S) is greater than 4, consider all
+		 * subsequent packets as belonging to a new loss interval. This
+		 * test is necessary since CCVal may wrap between intervals.
+		 */
+		cur->li_is_closed = 1;
+
+	if (tfrc_lh_length(lh) == 1)		/* due to RFC 3448, 6.3.1 */
+		return 0;
+
+	cur->li_length = length;
+	tfrc_lh_calc_i_mean(lh);
+
+	return (lh->i_mean < old_i_mean);
+}
+EXPORT_SYMBOL_GPL(tfrc_lh_update_i_mean);
+
 static int dccp_li_hist_interval_new(struct list_head *list,
 				     const u64 seq_loss, const u8 win_loss)
 {
@@ -284,6 +387,54 @@ void dccp_li_update_li(struct sock *sk,
 
 EXPORT_SYMBOL_GPL(dccp_li_update_li);
 
+/* Determine if `new_loss' does begin a new loss interval [RFC 4342, 10.2] */
+static inline u8 tfrc_lh_is_new_loss(struct tfrc_loss_interval *cur,
+				     struct tfrc_rx_hist_entry *new_loss)
+{
+	return	dccp_delta_seqno(cur->li_seqno, new_loss->tfrchrx_seqno) > 0 &&
+		(cur->li_is_closed || SUB16(new_loss->tfrchrx_ccval, cur->li_ccval) > 4);
+}
+
+/** tfrc_lh_interval_add  -  Insert new record into the Loss Interval database
+ * @lh:		   Loss Interval database
+ * @rh:		   Receive history containing a fresh loss event
+ * @calc_first_li: Caller-dependent routine to compute length of first interval
+ * @sk:		   Used by @calc_first_li in caller-specific way (subtyping)
+ * Updates I_mean and returns 1 if a new interval has in fact been added to @lh.
+ */
+int tfrc_lh_interval_add(struct tfrc_loss_hist *lh, struct tfrc_rx_hist *rh,
+			 u32 (*calc_first_li)(struct sock *), struct sock *sk)
+{
+	struct tfrc_loss_interval *cur = tfrc_lh_peek(lh), *new;
+
+	if (cur != NULL && !tfrc_lh_is_new_loss(cur, tfrc_rx_hist_loss_prev(rh)))
+		return 0;
+
+	new = tfrc_lh_demand_next(lh);
+	if (unlikely(new == NULL)) {
+		DCCP_CRIT("Cannot allocate/add loss record.");
+		return 0;
+	}
+
+	new->li_seqno	  = tfrc_rx_hist_loss_prev(rh)->tfrchrx_seqno;
+	new->li_ccval	  = tfrc_rx_hist_loss_prev(rh)->tfrchrx_ccval;
+	new->li_is_closed = 0;
+
+	if (++lh->counter == 1)
+		lh->i_mean = new->li_length = (*calc_first_li)(sk);
+	else {
+		cur->li_length = dccp_delta_seqno(cur->li_seqno, new->li_seqno);
+		new->li_length = dccp_delta_seqno(new->li_seqno,
+				  tfrc_rx_hist_last_rcv(rh)->tfrchrx_seqno);
+		if (lh->counter > (2*LIH_SIZE))
+			lh->counter -= LIH_SIZE;
+
+		tfrc_lh_calc_i_mean(lh);
+	}
+	return 1;
+}
+EXPORT_SYMBOL_GPL(tfrc_lh_interval_add);
+
 int __init dccp_li_init(void)
 {
 	dccp_li_cachep = kmem_cache_create("dccp_li_hist",
diff --git a/net/dccp/ccids/lib/loss_interval.h b/net/dccp/ccids/lib/loss_interval.h
index 27bee92..5e3c5c5 100644
--- a/net/dccp/ccids/lib/loss_interval.h
+++ b/net/dccp/ccids/lib/loss_interval.h
@@ -3,6 +3,7 @@
 /*
  *  net/dccp/ccids/lib/loss_interval.h
  *
+ *  Copyright (c) 2007   The University of Aberdeen, Scotland, UK
  *  Copyright (c) 2005-7 The University of Waikato, Hamilton, New Zealand.
  *  Copyright (c) 2005-7 Ian McDonald <ian.mcdonald@jandi.co.nz>
  *  Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
@@ -12,11 +13,64 @@
  *  Software Foundation; either version 2 of the License, or (at your option)
  *  any later version.
  */
-
 #include <linux/ktime.h>
 #include <linux/list.h>
+#include <linux/slab.h>
+
+/*
+ * Number of loss intervals (RFC 4342, 8.6.1). The history size is one more than
+ * NINTERVAL, since the `open' interval I_0 is always stored as the first entry.
+ */
+#define NINTERVAL	8
+#define LIH_SIZE	(NINTERVAL + 1)
+
+/**
+ *  tfrc_loss_interval  -  Loss history record for TFRC-based protocols
+ *  @li_seqno:		Highest received seqno before the start of loss
+ *  @li_ccval:		The CCVal belonging to @li_seqno
+ *  @li_is_closed:	Whether @li_seqno is older than 1 RTT
+ *  @li_length:		Loss interval sequence length
+ */
+struct tfrc_loss_interval {
+	u64		 li_seqno:48,
+			 li_ccval:4,
+			 li_is_closed:1;
+	u32		 li_length;
+};
+
+/**
+ *  tfrc_loss_hist  -  Loss record database
+ *  @ring:	Circular queue managed in LIFO manner
+ *  @counter:	Current count of entries (can be more than %LIH_SIZE)
+ *  @i_mean:	Current Average Loss Interval [RFC 3448, 5.4]
+ */
+struct tfrc_loss_hist {
+	struct tfrc_loss_interval	*ring[LIH_SIZE];
+	u8				counter;
+	u32				i_mean;
+};
+
+static inline void tfrc_lh_init(struct tfrc_loss_hist *lh)
+{
+	memset(lh, 0, sizeof(struct tfrc_loss_hist));
+}
+
+static inline u8 tfrc_lh_is_initialised(struct tfrc_loss_hist *lh)
+{
+	return lh->counter > 0;
+}
+
+static inline u8 tfrc_lh_length(struct tfrc_loss_hist *lh)
+{
+	return min(lh->counter, (u8)LIH_SIZE);
+}
 
 extern void dccp_li_hist_purge(struct list_head *list);
+struct tfrc_rx_hist;
+extern int  tfrc_lh_interval_add(struct tfrc_loss_hist *, struct tfrc_rx_hist *,
+				 u32 (*first_li)(struct sock *), struct sock *);
+extern u8   tfrc_lh_update_i_mean(struct tfrc_loss_hist *lh, struct sk_buff *);
+extern void tfrc_lh_cleanup(struct tfrc_loss_hist *lh);
 
 extern u32 dccp_li_hist_calc_i_mean(struct list_head *list);
 
diff --git a/net/dccp/ccids/lib/packet_history.c b/net/dccp/ccids/lib/packet_history.c
index 22114c6..9ed824f 100644
--- a/net/dccp/ccids/lib/packet_history.c
+++ b/net/dccp/ccids/lib/packet_history.c
@@ -214,6 +214,208 @@ int tfrc_rx_hist_new_loss_indicated(struct tfrc_rx_hist *h,
 }
 EXPORT_SYMBOL_GPL(tfrc_rx_hist_new_loss_indicated);
 
+static void tfrc_rx_hist_swap(struct tfrc_rx_hist *h, const u8 a, const u8 b)
+{
+	const u8 idx_a = tfrc_rx_hist_index(h, a),
+		 idx_b = tfrc_rx_hist_index(h, b);
+	struct tfrc_rx_hist_entry *tmp = h->ring[idx_a];
+
+	h->ring[idx_a] = h->ring[idx_b];
+	h->ring[idx_b] = tmp;
+}
+
+/*
+ * Private helper functions for loss detection.
+ *
+ * In the descriptions, `Si' refers to the sequence number of entry number i,
+ * whose NDP count is `Ni' (lower case is used for variables).
+ * Note: All __after_loss functions expect that a test against duplicates has
+ *       been performed already: the seqno of the skb must not be less than the
+ *       seqno of loss_prev; and it must not equal that of any valid hist_entry.
+ */
+static void __one_after_loss(struct tfrc_rx_hist *h, struct sk_buff *skb, u32 n2)
+{
+	u64 s0 = tfrc_rx_hist_loss_prev(h)->tfrchrx_seqno,
+	    s1 = tfrc_rx_hist_entry(h, 1)->tfrchrx_seqno,
+	    s2 = DCCP_SKB_CB(skb)->dccpd_seq;
+	int n1 = tfrc_rx_hist_entry(h, 1)->tfrchrx_ndp,
+	   d12 = dccp_delta_seqno(s1, s2), d2;
+
+	if (d12 > 0) {			/* S1  <  S2 */
+		h->loss_count = 2;
+		tfrc_rx_hist_entry_from_skb(tfrc_rx_hist_entry(h, 2), skb, n2);
+		return;
+	}
+
+	/* S0  <  S2  <  S1 */
+	d2 = dccp_delta_seqno(s0, s2);
+
+	if (d2 == 1 || n2 >= d2) {	/* S2 is direct successor of S0 */
+		int d21 = -d12;
+
+		if (d21 == 1 || n1 >= d21) {
+			/* hole is filled: S0, S2, and S1 are consecutive */
+			h->loss_count = 0;
+			h->loss_start = tfrc_rx_hist_index(h, 1);
+		} else
+			/* gap between S2 and S1: just update loss_prev */
+			tfrc_rx_hist_entry_from_skb(tfrc_rx_hist_loss_prev(h), skb, n2);
+
+	} else {			/* hole between S0 and S2 */
+		/*
+		 * Reorder history to insert S2 between S0 and s1
+		 */
+		tfrc_rx_hist_swap(h, 0, 3);
+		h->loss_start = tfrc_rx_hist_index(h, 3);
+		tfrc_rx_hist_entry_from_skb(tfrc_rx_hist_entry(h, 1), skb, n2);
+		h->loss_count = 2;
+	}
+}
+
+/* return 1 if a new loss event has been identified */
+static int __two_after_loss(struct tfrc_rx_hist *h, struct sk_buff *skb, u32 n3)
+{
+	u64 s0 = tfrc_rx_hist_loss_prev(h)->tfrchrx_seqno,
+	    s1 = tfrc_rx_hist_entry(h, 1)->tfrchrx_seqno,
+	    s2 = tfrc_rx_hist_entry(h, 2)->tfrchrx_seqno,
+	    s3 = DCCP_SKB_CB(skb)->dccpd_seq;
+	int n1 = tfrc_rx_hist_entry(h, 1)->tfrchrx_ndp,
+	   d23 = dccp_delta_seqno(s2, s3), d13, d3, d31;
+
+	if (d23 > 0) {			/* S2  <  S3 */
+		h->loss_count = 3;
+		tfrc_rx_hist_entry_from_skb(tfrc_rx_hist_entry(h, 3), skb, n3);
+		return 1;
+	}
+
+	/* S3  <  S2 */
+	d13 = dccp_delta_seqno(s1, s3);
+
+	if (d13 > 0) {
+		/*
+		 * The sequence number order is S1, S3, S2
+		 * Reorder history to insert entry between S1 and S2
+		 */
+		tfrc_rx_hist_swap(h, 2, 3);
+		tfrc_rx_hist_entry_from_skb(tfrc_rx_hist_entry(h, 2), skb, n3);
+		h->loss_count = 3;
+		return 1;
+	}
+
+	/* S0  <  S3  <  S1 */
+	d31 = -d13;
+	d3  = dccp_delta_seqno(s0, s3);
+
+	if (d3 == 1 || n3 >= d3) {	/* S3 is a successor of S0 */
+
+		if (d31 == 1 || n1 >= d31) {
+			/* hole between S0 and S1 filled by S3 */
+			int  d2 = dccp_delta_seqno(s1, s2),
+			     n2 = tfrc_rx_hist_entry(h, 2)->tfrchrx_ndp;
+
+			if (d2 == 1 || n2 >= d2) {
+				/* entire hole filled by S0, S3, S1, S2 */
+				h->loss_start = tfrc_rx_hist_index(h, 2);
+				h->loss_count = 0;
+			} else {
+				/* gap remains between S1 and S2 */
+				h->loss_start = tfrc_rx_hist_index(h, 1);
+				h->loss_count = 1;
+			}
+
+		} else /* gap exists between S3 and S1, loss_count stays at 2 */
+			tfrc_rx_hist_entry_from_skb(tfrc_rx_hist_loss_prev(h), skb, n3);
+
+		return 0;
+	}
+
+	/*
+	 * The remaining case: S3 is not a successor of S0.
+	 * Sequence order is S0, S3, S1, S2; reorder to insert between S0 and S1
+	 */
+	tfrc_rx_hist_swap(h, 0, 3);
+	h->loss_start = tfrc_rx_hist_index(h, 3);
+	tfrc_rx_hist_entry_from_skb(tfrc_rx_hist_entry(h, 1), skb, n3);
+	h->loss_count = 3;
+
+	return 1;
+}
+
+/* return the signed modulo-2^48 sequence number distance from entry e1 to e2 */
+static s64 tfrc_rx_hist_delta_seqno(struct tfrc_rx_hist *h, u8 e1, u8 e2)
+{
+	DCCP_BUG_ON(e1 > h->loss_count || e2 > h->loss_count);
+
+	return dccp_delta_seqno(tfrc_rx_hist_entry(h, e1)->tfrchrx_seqno,
+				tfrc_rx_hist_entry(h, e2)->tfrchrx_seqno);
+}
+
+/* recycle RX history records to continue loss detection if necessary */
+static void __three_after_loss(struct tfrc_rx_hist *h)
+{
+	/*
+	 * The distance between S0 and S1 is always greater than 1 and the NDP
+	 * count of S1 is smaller than this distance. Otherwise there would
+	 * have been no loss. Hence it is only necessary to see whether there
+	 * are further missing data packets between S1/S2 and S2/S3.
+	 */
+	int d2 = tfrc_rx_hist_delta_seqno(h, 1, 2),
+	    d3 = tfrc_rx_hist_delta_seqno(h, 2, 3),
+	    n2 = tfrc_rx_hist_entry(h, 2)->tfrchrx_ndp,
+	    n3 = tfrc_rx_hist_entry(h, 3)->tfrchrx_ndp;
+
+	if (d2 == 1 || n2 >= d2) {	/* S2 is successor to S1 */
+
+		if (d3 == 1 || n3 >= d3) {
+			/* S3 is successor of S2: entire hole is filled */
+			h->loss_start = tfrc_rx_hist_index(h, 3);
+			h->loss_count = 0;
+		} else {
+			/* gap between S2 and S3 */
+			h->loss_start = tfrc_rx_hist_index(h, 2);
+			h->loss_count = 1;
+		}
+
+	} else {			/* gap between S1 and S2 */
+		h->loss_start = tfrc_rx_hist_index(h, 1);
+		h->loss_count = 2;
+	}
+}
+
+/**
+ *  tfrc_rx_handle_loss  -  Loss detection and further processing
+ *  @h:		    The non-empty RX history object
+ *  @lh:	    Loss Intervals database to update
+ *  @skb:	    Currently received packet
+ *  @ndp:	    The NDP count belonging to @skb
+ *  @calc_first_li: Caller-dependent computation of first loss interval in @lh
+ *  @sk:	    Used by @calc_first_li (see tfrc_lh_interval_add)
+ *  Chooses action according to pending loss, updates LI database when a new
+ *  loss was detected, and does required post-processing. Returns 1 when caller
+ *  should send feedback, 0 otherwise.
+ */
+int tfrc_rx_handle_loss(struct tfrc_rx_hist *h,
+			struct tfrc_loss_hist *lh,
+			struct sk_buff *skb, u32 ndp,
+			u32 (*calc_first_li)(struct sock *), struct sock *sk)
+{
+	int is_new_loss = 0;
+
+	if (h->loss_count == 1) {
+		__one_after_loss(h, skb, ndp);
+	} else if (h->loss_count != 2) {
+		DCCP_BUG("invalid loss_count %d", h->loss_count);
+	} else if (__two_after_loss(h, skb, ndp)) {
+		/*
+		 * Update Loss Interval database and recycle RX records
+		 */
+		is_new_loss = tfrc_lh_interval_add(lh, h, calc_first_li, sk);
+		__three_after_loss(h);
+	}
+	return is_new_loss;
+}
+EXPORT_SYMBOL_GPL(tfrc_rx_handle_loss);
+
 int tfrc_rx_hist_alloc(struct tfrc_rx_hist *h)
 {
 	int i;
diff --git a/net/dccp/ccids/lib/packet_history.h b/net/dccp/ccids/lib/packet_history.h
index e58b0fc..24edd8d 100644
--- a/net/dccp/ccids/lib/packet_history.h
+++ b/net/dccp/ccids/lib/packet_history.h
@@ -36,10 +36,9 @@
 #ifndef _DCCP_PKT_HIST_
 #define _DCCP_PKT_HIST_
 
-#include <linux/ktime.h>
-#include <linux/types.h>
-
-struct sk_buff;
+#include <linux/list.h>
+#include <linux/slab.h>
+#include "tfrc.h"
 
 struct tfrc_tx_hist_entry;
 
@@ -125,6 +124,10 @@ extern void tfrc_rx_hist_add_packet(struct tfrc_rx_hist *h,
 extern int tfrc_rx_hist_duplicate(struct tfrc_rx_hist *h, struct sk_buff *skb);
 extern int tfrc_rx_hist_new_loss_indicated(struct tfrc_rx_hist *h,
 					   const struct sk_buff *skb, u32 ndp);
+struct tfrc_loss_hist;
+extern int  tfrc_rx_handle_loss(struct tfrc_rx_hist *, struct tfrc_loss_hist *,
+				struct sk_buff *skb, u32 ndp,
+				u32 (*first_li)(struct sock *), struct sock *);
 extern u32 tfrc_rx_hist_sample_rtt(struct tfrc_rx_hist *h,
 				   const struct sk_buff *skb);
 extern int tfrc_rx_hist_alloc(struct tfrc_rx_hist *h);
diff --git a/net/dccp/ccids/lib/tfrc.h b/net/dccp/ccids/lib/tfrc.h
index ab8848c..1fb1187 100644
--- a/net/dccp/ccids/lib/tfrc.h
+++ b/net/dccp/ccids/lib/tfrc.h
@@ -17,6 +17,9 @@
 #include <linux/types.h>
 #include <asm/div64.h>
 #include "../../dccp.h"
+/* internal includes that this module exports: */
+#include "loss_interval.h"
+#include "packet_history.h"
 
 #ifdef CONFIG_IP_DCCP_TFRC_DEBUG
 extern int tfrc_debug;
-- 
1.5.3.GIT


^ permalink raw reply related

* [PATCH 1/4] [PATCH v2] [TFRC]: Put RX/TX initialisation into tfrc.c
From: Gerrit Renker @ 2007-12-10 13:11 UTC (permalink / raw)
  To: acme; +Cc: dccp, netdev, Gerrit Renker
In-Reply-To: <1197292318-29659-1-git-send-email-gerrit@erg.abdn.ac.uk>

This separates RX/TX initialisation and puts all packet history / loss intervals
initialisation into tfrc.c.
The organisation is uniform: slab declaration -> {rx,tx}_init() -> {rx,tx}_exit()

Signed-off-by: Gerrit Renker <gerrit@erg.abdn.ac.uk>
---
 net/dccp/ccids/lib/packet_history.c |   68 ++++++++++++++++------------------
 net/dccp/ccids/lib/tfrc.c           |   31 ++++++++++++----
 2 files changed, 55 insertions(+), 44 deletions(-)

diff --git a/net/dccp/ccids/lib/packet_history.c b/net/dccp/ccids/lib/packet_history.c
index af44082..727b17d 100644
--- a/net/dccp/ccids/lib/packet_history.c
+++ b/net/dccp/ccids/lib/packet_history.c
@@ -57,6 +57,22 @@ struct tfrc_tx_hist_entry {
  */
 static struct kmem_cache *tfrc_tx_hist_slab;
 
+int __init tfrc_tx_packet_history_init(void)
+{
+	tfrc_tx_hist_slab = kmem_cache_create("tfrc_tx_hist",
+					      sizeof(struct tfrc_tx_hist_entry),
+					      0, SLAB_HWCACHE_ALIGN, NULL);
+	return tfrc_tx_hist_slab == NULL ? -ENOBUFS : 0;
+}
+
+void tfrc_tx_packet_history_exit(void)
+{
+	if (tfrc_tx_hist_slab != NULL) {
+		kmem_cache_destroy(tfrc_tx_hist_slab);
+		tfrc_tx_hist_slab = NULL;
+	}
+}
+
 static struct tfrc_tx_hist_entry *
 	tfrc_tx_hist_find_entry(struct tfrc_tx_hist_entry *head, u64 seqno)
 {
@@ -119,6 +135,22 @@ EXPORT_SYMBOL_GPL(tfrc_tx_hist_rtt);
  */
 static struct kmem_cache *tfrc_rx_hist_slab;
 
+int __init tfrc_rx_packet_history_init(void)
+{
+	tfrc_rx_hist_slab = kmem_cache_create("tfrc_rxh_cache",
+					      sizeof(struct tfrc_rx_hist_entry),
+					      0, SLAB_HWCACHE_ALIGN, NULL);
+	return tfrc_rx_hist_slab == NULL ? -ENOBUFS : 0;
+}
+
+void tfrc_rx_packet_history_exit(void)
+{
+	if (tfrc_rx_hist_slab != NULL) {
+		kmem_cache_destroy(tfrc_rx_hist_slab);
+		tfrc_rx_hist_slab = NULL;
+	}
+}
+
 /**
  * tfrc_rx_hist_index - index to reach n-th entry after loss_start
  */
@@ -316,39 +348,3 @@ keep_ref_for_next_time:
 	return sample;
 }
 EXPORT_SYMBOL_GPL(tfrc_rx_hist_sample_rtt);
-
-__init int packet_history_init(void)
-{
-	tfrc_tx_hist_slab = kmem_cache_create("tfrc_tx_hist",
-					      sizeof(struct tfrc_tx_hist_entry), 0,
-					      SLAB_HWCACHE_ALIGN, NULL);
-	if (tfrc_tx_hist_slab == NULL)
-		goto out_err;
-
-	tfrc_rx_hist_slab = kmem_cache_create("tfrc_rx_hist",
-					      sizeof(struct tfrc_rx_hist_entry), 0,
-					      SLAB_HWCACHE_ALIGN, NULL);
-	if (tfrc_rx_hist_slab == NULL)
-		goto out_free_tx;
-
-	return 0;
-
-out_free_tx:
-	kmem_cache_destroy(tfrc_tx_hist_slab);
-	tfrc_tx_hist_slab = NULL;
-out_err:
-	return -ENOBUFS;
-}
-
-void packet_history_exit(void)
-{
-	if (tfrc_tx_hist_slab != NULL) {
-		kmem_cache_destroy(tfrc_tx_hist_slab);
-		tfrc_tx_hist_slab = NULL;
-	}
-
-	if (tfrc_rx_hist_slab != NULL) {
-		kmem_cache_destroy(tfrc_rx_hist_slab);
-		tfrc_rx_hist_slab = NULL;
-	}
-}
diff --git a/net/dccp/ccids/lib/tfrc.c b/net/dccp/ccids/lib/tfrc.c
index 3a7a183..20763fa 100644
--- a/net/dccp/ccids/lib/tfrc.c
+++ b/net/dccp/ccids/lib/tfrc.c
@@ -14,27 +14,42 @@ module_param(tfrc_debug, bool, 0444);
 MODULE_PARM_DESC(tfrc_debug, "Enable debug messages");
 #endif
 
+extern int  tfrc_tx_packet_history_init(void);
+extern void tfrc_tx_packet_history_exit(void);
+extern int  tfrc_rx_packet_history_init(void);
+extern void tfrc_rx_packet_history_exit(void);
+
 extern int  dccp_li_init(void);
 extern void dccp_li_exit(void);
-extern int packet_history_init(void);
-extern void packet_history_exit(void);
 
 static int __init tfrc_module_init(void)
 {
 	int rc = dccp_li_init();
 
-	if (rc == 0) {
-		rc = packet_history_init();
-		if (rc != 0)
-			dccp_li_exit();
-	}
+	if (rc)
+		goto out;
+
+	rc = tfrc_tx_packet_history_init();
+	if (rc)
+		goto out_free_loss_intervals;
 
+	rc = tfrc_rx_packet_history_init();
+	if (rc)
+		goto out_free_tx_history;
+	return 0;
+
+out_free_tx_history:
+	tfrc_tx_packet_history_exit();
+out_free_loss_intervals:
+	dccp_li_exit();
+out:
 	return rc;
 }
 
 static void __exit tfrc_module_exit(void)
 {
-	packet_history_exit();
+	tfrc_rx_packet_history_exit();
+	tfrc_tx_packet_history_exit();
 	dccp_li_exit();
 }
 
-- 
1.5.3.GIT


^ permalink raw reply related

* [PATCH 4/4] [CCID3]: Redundant debugging output / documentation
From: Gerrit Renker @ 2007-12-10 13:11 UTC (permalink / raw)
  To: acme; +Cc: dccp, netdev, Gerrit Renker
In-Reply-To: <1197292318-29659-4-git-send-email-gerrit@erg.abdn.ac.uk>

Each time feedback is sent two lines are printed:

	ccid3_hc_rx_send_feedback: client ... - entry
	ccid3_hc_rx_send_feedback: Interval ...usec, X_recv=..., 1/p=...

The first line is redundant and thus removed.

Further, documentation of ccid3_hc_rx_sock (capitalisation) is made consistent.

Signed-off-by: Gerrit Renker <gerrit@erg.abdn.ac.uk>
---
 net/dccp/ccids/ccid3.c |    2 --
 net/dccp/ccids/ccid3.h |    4 ++--
 2 files changed, 2 insertions(+), 4 deletions(-)

diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c
index 60fcb31..b92069b 100644
--- a/net/dccp/ccids/ccid3.c
+++ b/net/dccp/ccids/ccid3.c
@@ -685,8 +685,6 @@ static void ccid3_hc_rx_send_feedback(struct sock *sk,
 	ktime_t now;
 	s64 delta = 0;
 
-	ccid3_pr_debug("%s(%p) - entry \n", dccp_role(sk), sk);
-
 	if (unlikely(hcrx->ccid3hcrx_state == TFRC_RSTATE_TERM))
 		return;
 
diff --git a/net/dccp/ccids/ccid3.h b/net/dccp/ccids/ccid3.h
index 3c33dc6..6ceeb80 100644
--- a/net/dccp/ccids/ccid3.h
+++ b/net/dccp/ccids/ccid3.h
@@ -135,9 +135,9 @@ enum ccid3_hc_rx_states {
  *
  *  @ccid3hcrx_x_recv  -  Receiver estimate of send rate (RFC 3448 4.3)
  *  @ccid3hcrx_rtt  -  Receiver estimate of rtt (non-standard)
- *  @ccid3hcrx_p  -  current loss event rate (RFC 3448 5.4)
+ *  @ccid3hcrx_p  -  Current loss event rate (RFC 3448 5.4)
  *  @ccid3hcrx_last_counter  -  Tracks window counter (RFC 4342, 8.1)
- *  @ccid3hcrx_state  -  receiver state, one of %ccid3_hc_rx_states
+ *  @ccid3hcrx_state  -  Receiver state, one of %ccid3_hc_rx_states
  *  @ccid3hcrx_bytes_recv  -  Total sum of DCCP payload bytes
  *  @ccid3hcrx_tstamp_last_feedback  -  Time at which last feedback was sent
  *  @ccid3hcrx_tstamp_last_ack  -  Time at which last feedback was sent
-- 
1.5.3.GIT


^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox