Re: [PATCH 9/13] [SCTP] Merge IPv4 and IPv6 versions of get_saddr() with their corresponding get_dst().
On 10/27/06 20:47, Sridhar Samudrala wrote: On Tue, 2006-10-17 at 03:19 +0300, Ville Nuorvala wrote: As the IPv6 route lookup now also returns the selected source address there is no need for a separate source address lookup. In fact, the source address selection needs to be moved to get_dst() because the selected IPv6 source address isn't always stored in the route. Sometimes this makes it impossible to guess the correct address later on. Ville, Overall the patch looks pretty good. I found only 1 issue in sctp_v6_get_dst(). See below. snip +/* Returns the dst cache entry for the given source and destination ip + * addresses. + */ +static struct dst_entry *sctp_v6_get_dst(struct sctp_association *asoc, + union sctp_addr *daddr, + union sctp_addr *saddr) +{ +struct dst_entry *dst; +struct flowi fl; +struct sctp_bind_addr *bp; +rwlock_t *addr_lock; +struct sctp_sockaddr_entry *laddr; +struct list_head *pos; +struct rt6_info *rt; +union sctp_addr baddr; +sctp_scope_t scope; +__u8 matchlen = 0; +__u8 bmatchlen; + +memset(fl, 0, sizeof(fl)); +ipv6_addr_copy(fl.fl6_dst, daddr-v6.sin6_addr); +if (ipv6_addr_type(daddr-v6.sin6_addr) IPV6_ADDR_LINKLOCAL) +fl.oif = daddr-v6.sin6_scope_id; + +ipv6_addr_copy(fl.fl6_src, saddr-v6.sin6_addr); +SCTP_DEBUG_PRINTK(%s: DST= NIP6_FMT SRC= NIP6_FMT , + __FUNCTION__, NIP6(fl.fl6_dst), NIP6(fl.fl6_src)); + +dst = ip6_route_output(NULL, fl); +if (dst-error) { +dst_release(dst); +dst = NULL; +} +if (!ipv6_addr_any(saddr-v6.sin6_addr)) +goto out; +if (!asoc) { +if (dst) +ipv6_addr_copy(saddr-v6.sin6_addr, fl.fl6_src); +goto out; +} +bp = asoc-base.bind_addr; +addr_lock = asoc-base.addr_lock; + +if (dst) { +/* Walk through the bind address list and look for a bind + * address that matches the source address of the returned rt. + */ +sctp_v6_fl_saddr(baddr, fl, bp-port); Here we are checking if the source address returned in the dst matches one of the address in the bind address list of the association. Not the source address that is passed to this routine(it could be INADDRY_ANY). So this should be changed back to sctp_v6_dst_saddr(). No, see that's the problem. The source address isn't always stored in the rt6_info. Therefore I copy the address into the flowi, so after ip6_route_output() fl does indeed contain the selected source address. Sorry if I didn't cc you all relevant patches from the patch set. Anyway there are still some unresolved issues with my code, but it's nice to know I didn't at least mess up SCTP in a big way ;-) Thanks, Ville - To unsubscribe from this list: send the line unsubscribe netdev in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 9/13] [SCTP] Merge IPv4 and IPv6 versions of get_saddr() with their corresponding get_dst().
On Thu, 2006-11-02 at 14:32 +0200, Ville Nuorvala wrote: On 10/27/06 20:47, Sridhar Samudrala wrote: On Tue, 2006-10-17 at 03:19 +0300, Ville Nuorvala wrote: As the IPv6 route lookup now also returns the selected source address there is no need for a separate source address lookup. In fact, the source address selection needs to be moved to get_dst() because the selected IPv6 source address isn't always stored in the route. Sometimes this makes it impossible to guess the correct address later on. Ville, Overall the patch looks pretty good. I found only 1 issue in sctp_v6_get_dst(). See below. snip +/* Returns the dst cache entry for the given source and destination ip + * addresses. + */ +static struct dst_entry *sctp_v6_get_dst(struct sctp_association *asoc, + union sctp_addr *daddr, + union sctp_addr *saddr) +{ + struct dst_entry *dst; + struct flowi fl; + struct sctp_bind_addr *bp; + rwlock_t *addr_lock; + struct sctp_sockaddr_entry *laddr; + struct list_head *pos; + struct rt6_info *rt; + union sctp_addr baddr; + sctp_scope_t scope; + __u8 matchlen = 0; + __u8 bmatchlen; + + memset(fl, 0, sizeof(fl)); + ipv6_addr_copy(fl.fl6_dst, daddr-v6.sin6_addr); + if (ipv6_addr_type(daddr-v6.sin6_addr) IPV6_ADDR_LINKLOCAL) + fl.oif = daddr-v6.sin6_scope_id; + + ipv6_addr_copy(fl.fl6_src, saddr-v6.sin6_addr); + SCTP_DEBUG_PRINTK(%s: DST= NIP6_FMT SRC= NIP6_FMT , +__FUNCTION__, NIP6(fl.fl6_dst), NIP6(fl.fl6_src)); + + dst = ip6_route_output(NULL, fl); + if (dst-error) { + dst_release(dst); + dst = NULL; + } + if (!ipv6_addr_any(saddr-v6.sin6_addr)) + goto out; + if (!asoc) { + if (dst) + ipv6_addr_copy(saddr-v6.sin6_addr, fl.fl6_src); + goto out; + } + bp = asoc-base.bind_addr; + addr_lock = asoc-base.addr_lock; + + if (dst) { + /* Walk through the bind address list and look for a bind + * address that matches the source address of the returned rt. + */ + sctp_v6_fl_saddr(baddr, fl, bp-port); Here we are checking if the source address returned in the dst matches one of the address in the bind address list of the association. Not the source address that is passed to this routine(it could be INADDRY_ANY). So this should be changed back to sctp_v6_dst_saddr(). No, see that's the problem. The source address isn't always stored in the rt6_info. Therefore I copy the address into the flowi, so after ip6_route_output() fl does indeed contain the selected source address. Sorry if I didn't cc you all relevant patches from the patch set. When you said that IPV6 route lookup returns the selected source address, i assumed it will be returned via rt6_info-rt6i_src. But looks like it is returned in fl-fl6_src. If so, there is no problem. Why is rt6i_src not filled in some cases? I noticed this problem when i ran SCTP frametests that use a IP simulator in userspace. We have our own ip6_route_output that i modified to set source in rt6_info and not fl. Thanks Sridhar Anyway there are still some unresolved issues with my code, but it's nice to know I didn't at least mess up SCTP in a big way ;-) Thanks, Ville - To unsubscribe from this list: send the line unsubscribe netdev in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 9/13] [SCTP] Merge IPv4 and IPv6 versions of get_saddr() with their corresponding get_dst().
On Tue, 2006-10-17 at 03:19 +0300, Ville Nuorvala wrote: As the IPv6 route lookup now also returns the selected source address there is no need for a separate source address lookup. In fact, the source address selection needs to be moved to get_dst() because the selected IPv6 source address isn't always stored in the route. Sometimes this makes it impossible to guess the correct address later on. Ville, Overall the patch looks pretty good. I found only 1 issue in sctp_v6_get_dst(). See below. snip +/* Returns the dst cache entry for the given source and destination ip + * addresses. + */ +static struct dst_entry *sctp_v6_get_dst(struct sctp_association *asoc, + union sctp_addr *daddr, + union sctp_addr *saddr) +{ + struct dst_entry *dst; + struct flowi fl; + struct sctp_bind_addr *bp; + rwlock_t *addr_lock; + struct sctp_sockaddr_entry *laddr; + struct list_head *pos; + struct rt6_info *rt; + union sctp_addr baddr; + sctp_scope_t scope; + __u8 matchlen = 0; + __u8 bmatchlen; + + memset(fl, 0, sizeof(fl)); + ipv6_addr_copy(fl.fl6_dst, daddr-v6.sin6_addr); + if (ipv6_addr_type(daddr-v6.sin6_addr) IPV6_ADDR_LINKLOCAL) + fl.oif = daddr-v6.sin6_scope_id; + + ipv6_addr_copy(fl.fl6_src, saddr-v6.sin6_addr); + SCTP_DEBUG_PRINTK(%s: DST= NIP6_FMT SRC= NIP6_FMT , + __FUNCTION__, NIP6(fl.fl6_dst), NIP6(fl.fl6_src)); + + dst = ip6_route_output(NULL, fl); + if (dst-error) { + dst_release(dst); + dst = NULL; + } + if (!ipv6_addr_any(saddr-v6.sin6_addr)) + goto out; + if (!asoc) { + if (dst) + ipv6_addr_copy(saddr-v6.sin6_addr, fl.fl6_src); + goto out; + } + bp = asoc-base.bind_addr; + addr_lock = asoc-base.addr_lock; + + if (dst) { + /* Walk through the bind address list and look for a bind + * address that matches the source address of the returned rt. + */ + sctp_v6_fl_saddr(baddr, fl, bp-port); Here we are checking if the source address returned in the dst matches one of the address in the bind address list of the association. Not the source address that is passed to this routine(it could be INADDRY_ANY). So this should be changed back to sctp_v6_dst_saddr(). Thanks Sridhar + sctp_read_lock(addr_lock); + list_for_each(pos, bp-address_list) { + laddr = list_entry(pos, struct sctp_sockaddr_entry, +list); + if (!laddr-use_as_src) + continue; + if (sctp_v6_cmp_addr(baddr, laddr-a)) + goto init_saddr; + } + sctp_read_unlock(addr_lock); + + /* Invalid rt or none of the bound addresses match the source + * address. So release it. + */ + dst_release(dst); + dst = NULL; + } + + /* Go through the bind address list and find the best source address + * that matches the scope of the destination address. + */ + memset(baddr, 0, sizeof(union sctp_addr)); + scope = sctp_scope(daddr); + sctp_read_lock(addr_lock); + list_for_each(pos, bp-address_list) { + laddr = list_entry(pos, struct sctp_sockaddr_entry, list); + + if (!laddr-use_as_src || + laddr-a.sa.sa_family != AF_INET6 || + scope sctp_scope(laddr-a) || + (ipv6_addr_type(laddr-a.v6.sin6_addr) + IPV6_ADDR_LINKLOCAL + laddr-a.v6.sin6_scope_id != fl.oif)) + continue; + + bmatchlen = sctp_v6_addr_match_len(daddr, laddr-a); + if (!dst || (matchlen bmatchlen)) { + struct dst_entry *dst2; + ipv6_addr_copy(fl.fl6_src, laddr-a.v6.sin6_addr); + dst2 = ip6_route_output(NULL, fl); + if (dst2-error) { + dst_release(dst2); + dst2 = NULL; + continue; + } + dst_release(dst); + dst = dst2; + memcpy(baddr, laddr-a, sizeof(union sctp_addr)); + matchlen = bmatchlen; + } + } + if (dst) + goto init_saddr; +out_unlock: + sctp_read_unlock(addr_lock); +out: + if (dst) { + rt = (struct rt6_info *) dst; + SCTP_DEBUG_PRINTK(SRC= NIP6_FMT +rt6_dst= NIP6_FMT +rt6_src= NIP6_FMT \n, +
Re: [PATCH 9/13] [SCTP] Merge IPv4 and IPv6 versions of get_saddr() with their corresponding get_dst().
Ville Nuorvala wrote: As the IPv6 route lookup now also returns the selected source address there is no need for a separate source address lookup. In fact, the source address selection needs to be moved to get_dst() because the selected IPv6 source address isn't always stored in the route. Sometimes this makes it impossible to guess the correct address later on. I remember having to do a separate call to ipv6_get_saddr() specifically because ip6_route_output() didn't fill in the source address. Now if the route lookup also returns the source address, it looks logical to remove the separate source address lookup. So i agree with the idea behind the patch. I will review the patch in detail and try it out next week to see that it doesn't break SCTP and get back to you. I guess this is targeted for 2.6.20. Is that right? Thanks Sridhar - To unsubscribe from this list: send the line unsubscribe netdev in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 9/13] [SCTP] Merge IPv4 and IPv6 versions of get_saddr() with their corresponding get_dst().
As the IPv6 route lookup now also returns the selected source address there is no need for a separate source address lookup. In fact, the source address selection needs to be moved to get_dst() because the selected IPv6 source address isn't always stored in the route. Sometimes this makes it impossible to guess the correct address later on. Signed-off-by: Ville Nuorvala [EMAIL PROTECTED] --- include/net/sctp/structs.h |7 - net/sctp/ipv6.c| 235 +++- net/sctp/protocol.c| 56 -- net/sctp/transport.c |8 + 4 files changed, 148 insertions(+), 158 deletions(-) diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index c6d93bb..e0973a3 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h @@ -529,15 +529,8 @@ struct sctp_af { struct dst_entry *(*get_dst)(struct sctp_association *asoc, union sctp_addr *daddr, union sctp_addr *saddr); - void(*get_saddr)(struct sctp_association *asoc, -struct dst_entry *dst, -union sctp_addr *daddr, -union sctp_addr *saddr); void(*copy_addrlist) (struct list_head *, struct net_device *); - void(*dst_saddr)(union sctp_addr *saddr, -struct dst_entry *dst, -unsigned short port); int (*cmp_addr) (const union sctp_addr *addr1, const union sctp_addr *addr2); void(*addr_copy)(union sctp_addr *dst, diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index 78071c6..68ead54 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c @@ -188,46 +188,6 @@ static int sctp_v6_xmit(struct sk_buff * return ip6_xmit(sk, skb, fl, np-opt, ipfragok); } -/* Returns the dst cache entry for the given source and destination ip - * addresses. - */ -static struct dst_entry *sctp_v6_get_dst(struct sctp_association *asoc, -union sctp_addr *daddr, -union sctp_addr *saddr) -{ - struct dst_entry *dst; - struct flowi fl; - - memset(fl, 0, sizeof(fl)); - ipv6_addr_copy(fl.fl6_dst, daddr-v6.sin6_addr); - if (ipv6_addr_type(daddr-v6.sin6_addr) IPV6_ADDR_LINKLOCAL) - fl.oif = daddr-v6.sin6_scope_id; - - - SCTP_DEBUG_PRINTK(%s: DST= NIP6_FMT , - __FUNCTION__, NIP6(fl.fl6_dst)); - - if (saddr) { - ipv6_addr_copy(fl.fl6_src, saddr-v6.sin6_addr); - SCTP_DEBUG_PRINTK( - SRC= NIP6_FMT - , - NIP6(fl.fl6_src)); - } - - dst = ip6_route_output(NULL, fl); - if (!dst-error) { - struct rt6_info *rt; - rt = (struct rt6_info *)dst; - SCTP_DEBUG_PRINTK( - rt6_dst: NIP6_FMT rt6_src: NIP6_FMT \n, - NIP6(rt-rt6i_dst.addr), NIP6(rt-rt6i_src.addr)); - return dst; - } - SCTP_DEBUG_PRINTK(NO ROUTE\n); - dst_release(dst); - return NULL; -} - /* Returns the number of consecutive initial bits that match in the 2 ipv6 * addresses. */ @@ -250,69 +210,6 @@ static inline int sctp_v6_addr_match_len return (i*32); } -/* Fills in the source address(saddr) based on the destination address(daddr) - * and asoc's bind address list. - */ -static void sctp_v6_get_saddr(struct sctp_association *asoc, - struct dst_entry *dst, - union sctp_addr *daddr, - union sctp_addr *saddr) -{ - struct sctp_bind_addr *bp; - rwlock_t *addr_lock; - struct sctp_sockaddr_entry *laddr; - struct list_head *pos; - sctp_scope_t scope; - union sctp_addr *baddr = NULL; - __u8 matchlen = 0; - __u8 bmatchlen; - - SCTP_DEBUG_PRINTK(%s: asoc:%p dst:%p - daddr: NIP6_FMT , - __FUNCTION__, asoc, dst, NIP6(daddr-v6.sin6_addr)); - - if (!asoc) { - ipv6_get_saddr(dst, daddr-v6.sin6_addr,saddr-v6.sin6_addr); - SCTP_DEBUG_PRINTK(saddr from ipv6_get_saddr: NIP6_FMT \n, - NIP6(saddr-v6.sin6_addr)); - return; - } - - scope = sctp_scope(daddr); - - bp = asoc-base.bind_addr; - addr_lock = asoc-base.addr_lock; - - /* Go through the bind address list and find the best source address -* that matches the scope of the destination address. -*/ - sctp_read_lock(addr_lock); -