Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
e8ece35b
Commit
e8ece35b
authored
Oct 29, 2002
by
Sridhar Samudrala
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[SCTP]: Initial souce address selection support.
parent
f64d4b67
Changes
9
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
192 additions
and
52 deletions
+192
-52
include/net/sctp/structs.h
include/net/sctp/structs.h
+11
-2
net/sctp/associola.c
net/sctp/associola.c
+3
-0
net/sctp/input.c
net/sctp/input.c
+3
-2
net/sctp/ipv6.c
net/sctp/ipv6.c
+48
-21
net/sctp/output.c
net/sctp/output.c
+8
-7
net/sctp/protocol.c
net/sctp/protocol.c
+31
-16
net/sctp/sm_make_chunk.c
net/sctp/sm_make_chunk.c
+10
-3
net/sctp/sm_statefuns.c
net/sctp/sm_statefuns.c
+5
-0
net/sctp/transport.c
net/sctp/transport.c
+73
-1
No files found.
include/net/sctp/structs.h
View file @
e8ece35b
...
...
@@ -246,7 +246,10 @@ typedef struct sctp_func {
int
optname
,
char
*
optval
,
int
*
optlen
);
int
(
*
get_dst_mtu
)
(
const
sockaddr_storage_t
*
address
);
struct
dst_entry
*
(
*
get_dst
)
(
sockaddr_storage_t
*
daddr
,
sockaddr_storage_t
*
saddr
);
int
(
*
cmp_saddr
)
(
struct
dst_entry
*
dst
,
sockaddr_storage_t
*
saddr
);
__u16
net_header_len
;
int
sockaddr_len
;
sa_family_t
sa_family
;
...
...
@@ -476,6 +479,8 @@ struct SCTP_chunk {
/* What is the origin IP address for this chunk? */
sockaddr_storage_t
source
;
/* Destination address for this chunk. */
sockaddr_storage_t
dest
;
/* For an inbound chunk, this tells us where it came from.
* For an outbound chunk, it tells us where we'd like it to
...
...
@@ -492,7 +497,7 @@ void *sctp_addto_chunk(sctp_chunk_t *chunk, int len, const void *data);
int
sctp_user_addto_chunk
(
sctp_chunk_t
*
chunk
,
int
len
,
struct
iovec
*
data
);
sctp_chunk_t
*
sctp_chunkify
(
struct
sk_buff
*
,
const
sctp_association_t
*
,
struct
sock
*
);
void
sctp_init_
source
(
sctp_chunk_t
*
chunk
);
void
sctp_init_
addrs
(
sctp_chunk_t
*
chunk
);
const
sockaddr_storage_t
*
sctp_source
(
const
sctp_chunk_t
*
chunk
);
/* This is a structure for holding either an IPv6 or an IPv4 address. */
...
...
@@ -655,6 +660,9 @@ struct SCTP_transport {
/* PMTU : The current known path MTU. */
__u32
pmtu
;
/* Destination */
struct
dst_entry
*
dst
;
/* When was the last time(in jiffies) that a data packet was sent on
* this transport? This is used to adjust the cwnd when the transport
* becomes inactive.
...
...
@@ -735,6 +743,7 @@ extern sctp_transport_t *sctp_transport_new(const sockaddr_storage_t *, int);
extern
sctp_transport_t
*
sctp_transport_init
(
sctp_transport_t
*
,
const
sockaddr_storage_t
*
,
int
);
extern
void
sctp_transport_set_owner
(
sctp_transport_t
*
,
sctp_association_t
*
);
extern
void
sctp_transport_route
(
sctp_transport_t
*
,
sockaddr_storage_t
*
);
extern
void
sctp_transport_free
(
sctp_transport_t
*
);
extern
void
sctp_transport_destroy
(
sctp_transport_t
*
);
extern
void
sctp_transport_reset_timers
(
sctp_transport_t
*
);
...
...
net/sctp/associola.c
View file @
e8ece35b
...
...
@@ -404,6 +404,9 @@ sctp_transport_t *sctp_assoc_add_peer(sctp_association_t *asoc,
sctp_transport_set_owner
(
peer
,
asoc
);
/* Cache a route for the transport. */
sctp_transport_route
(
peer
,
NULL
);
/* If this is the first transport addr on this association,
* initialize the association PMTU to the peer's PMTU.
* If not and the current association PMTU is higher than the new
...
...
net/sctp/input.c
View file @
e8ece35b
...
...
@@ -41,6 +41,7 @@
* Jon Grimm <jgrimm@us.ibm.com>
* Hui Huang <hui.huang@nokia.com>
* Daisy Chang <daisyc@us.ibm.com>
* Sridhar Samudrala <sri@us.ibm.com>
*
* Any bugs reported given to us we will try to fix... any fixes shared will
* be incorporated into the next SCTP release.
...
...
@@ -217,8 +218,8 @@ int sctp_rcv(struct sk_buff *skb)
/* Remember the SCTP header. */
chunk
->
sctp_hdr
=
sh
;
/* Set the source a
ddress
. */
sctp_init_
source
(
chunk
);
/* Set the source a
nd destination addresses of the incoming chunk
. */
sctp_init_
addrs
(
chunk
);
/* Remember where we came from. */
chunk
->
transport
=
transport
;
...
...
net/sctp/ipv6.c
View file @
e8ece35b
...
...
@@ -158,35 +158,61 @@ static inline int sctp_v6_xmit(struct sk_buff *skb)
}
#endif
/* TEST_FRAME */
/* Returns the mtu for the given v6 destination address. */
int
sctp_v6_get_dst_mtu
(
const
sockaddr_storage_t
*
address
)
/* FIXME: This macro needs to be moved to a common header file. */
#define NIP6(addr) \
ntohs((addr)->s6_addr16[0]), \
ntohs((addr)->s6_addr16[1]), \
ntohs((addr)->s6_addr16[2]), \
ntohs((addr)->s6_addr16[3]), \
ntohs((addr)->s6_addr16[4]), \
ntohs((addr)->s6_addr16[5]), \
ntohs((addr)->s6_addr16[6]), \
ntohs((addr)->s6_addr16[7])
/* Returns the dst cache entry for the given source and destination ip
* addresses.
*/
struct
dst_entry
*
sctp_v6_get_dst
(
sockaddr_storage_t
*
daddr
,
sockaddr_storage_t
*
saddr
)
{
struct
dst_entry
*
dst
;
struct
flowi
fl
;
int
dst_mtu
=
SCTP_DEFAULT_MAXSEGMENT
;
struct
flowi
fl
=
{
.
nl_u
=
{
.
ip6_u
=
{
.
daddr
=
&
daddr
->
v6
.
sin6_addr
,
}
}
}
;
fl
.
proto
=
0
;
fl
.
fl6_dst
=
(
struct
in6_addr
*
)
&
address
->
v6
.
sin6_addr
;
fl
.
fl6_src
=
NULL
;
fl
.
fl6_flowlabel
=
0
;
fl
.
oif
=
0
;
fl
.
uli_u
.
ports
.
sport
=
0
;
fl
.
uli_u
.
ports
.
dport
=
0
;
SCTP_DEBUG_PRINTK
(
"%s: DST=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x "
,
__FUNCTION__
,
NIP6
(
fl
.
fl6_dst
));
if
(
saddr
)
{
fl
.
fl6_src
=
&
saddr
->
v6
.
sin6_addr
;
SCTP_DEBUG_PRINTK
(
"SRC=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x - "
,
NIP6
(
fl
.
fl6_src
));
}
dst
=
ip6_route_output
(
NULL
,
&
fl
);
if
(
dst
)
{
dst_mtu
=
dst
->
pmtu
;
SCTP_DEBUG_PRINTK
(
"sctp_v6_get_dst_mtu: "
"ip6_route_output: dev:%s pmtu:%d
\n
"
,
dst
->
dev
->
name
,
dst_mtu
);
dst_release
(
dst
);
struct
rt6_info
*
rt
;
rt
=
(
struct
rt6_info
*
)
dst
;
SCTP_DEBUG_PRINTK
(
"rt6_dst:%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x "
"rt6_src:%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x
\n
"
,
NIP6
(
&
rt
->
rt6i_dst
.
addr
),
NIP6
(
&
rt
->
rt6i_src
.
addr
));
}
else
{
SCTP_DEBUG_PRINTK
(
"sctp_v6_get_dst_mtu: "
"ip6_route_output failed, returning "
"%d as dst_mtu
\n
"
,
dst_mtu
);
SCTP_DEBUG_PRINTK
(
"NO ROUTE
\n
"
);
return
NULL
;
}
return
dst_mtu
;
return
dst
;
}
/* Check if the dst entry's source addr matches the given source addr. */
int
sctp_v6_cmp_saddr
(
struct
dst_entry
*
dst
,
sockaddr_storage_t
*
saddr
)
{
struct
rt6_info
*
rt
=
(
struct
rt6_info
*
)
dst
;
return
ipv6_addr_cmp
(
&
rt
->
rt6i_src
.
addr
,
&
saddr
->
v6
.
sin6_addr
);
}
/* Initialize a PF_INET6 socket msg_name. */
...
...
@@ -301,7 +327,8 @@ static sctp_func_t sctp_ipv6_specific = {
.
queue_xmit
=
sctp_v6_xmit
,
.
setsockopt
=
ipv6_setsockopt
,
.
getsockopt
=
ipv6_getsockopt
,
.
get_dst_mtu
=
sctp_v6_get_dst_mtu
,
.
get_dst
=
sctp_v6_get_dst
,
.
cmp_saddr
=
sctp_v6_cmp_saddr
,
.
net_header_len
=
sizeof
(
struct
ipv6hdr
),
.
sockaddr_len
=
sizeof
(
struct
sockaddr_in6
),
.
sa_family
=
AF_INET6
,
...
...
net/sctp/output.c
View file @
e8ece35b
...
...
@@ -245,6 +245,7 @@ int sctp_packet_transmit(sctp_packet_t *packet)
int
err
=
0
;
int
padding
;
/* How much padding do we need? */
__u8
packet_has_data
=
0
;
struct
dst_entry
*
dst
;
/* Do NOT generate a chunkless packet... */
if
(
skb_queue_empty
(
&
packet
->
chunks
))
...
...
@@ -410,13 +411,6 @@ int sctp_packet_transmit(sctp_packet_t *packet)
asoc
->
peer
.
last_sent_to
=
transport
;
}
/* Hey, before Linux changes, here's what we have to
* do to force IP routing to recognize the change of
* dest addr. --xguo
*/
if
(
sk
->
dst_cache
)
sk
->
dst_cache
->
obsolete
=
1
;
if
(
packet_has_data
)
{
struct
timer_list
*
timer
;
unsigned
long
timeout
;
...
...
@@ -434,6 +428,13 @@ int sctp_packet_transmit(sctp_packet_t *packet)
}
}
dst
=
transport
->
dst
;
if
(
!
dst
||
dst
->
obsolete
)
{
sctp_transport_route
(
transport
,
NULL
);
}
nskb
->
dst
=
dst_clone
(
transport
->
dst
);
SCTP_DEBUG_PRINTK
(
"***sctp_transmit_packet*** skb length %d
\n
"
,
nskb
->
len
);
(
*
transport
->
af_specific
->
queue_xmit
)(
nskb
);
...
...
net/sctp/protocol.c
View file @
e8ece35b
...
...
@@ -256,27 +256,41 @@ int sctp_copy_local_addr_list(sctp_protocol_t *proto, sctp_bind_addr_t *bp,
return
error
;
}
/* Returns the mtu for the given v4 destination address. */
int
sctp_v4_get_dst_mtu
(
const
sockaddr_storage_t
*
address
)
/* Returns the dst cache entry for the given source and destination ip
* addresses.
*/
struct
dst_entry
*
sctp_v4_get_dst
(
sockaddr_storage_t
*
daddr
,
sockaddr_storage_t
*
saddr
)
{
int
dst_mtu
=
SCTP_DEFAULT_MAXSEGMENT
;
struct
rtable
*
rt
;
struct
flowi
fl
=
{
.
nl_u
=
{
.
ip4_u
=
{
.
daddr
=
address
->
v4
.
sin_addr
.
s_addr
}
}
};
struct
flowi
fl
=
{
.
nl_u
=
{
.
ip4_u
=
{
.
daddr
=
daddr
->
v4
.
sin_addr
.
s_addr
,
}
}
};
if
(
saddr
)
fl
.
fl4_src
=
saddr
->
v4
.
sin_addr
.
s_addr
;
SCTP_DEBUG_PRINTK
(
"%s: DST:%u.%u.%u.%u, SRC:%u.%u.%u.%u - "
,
__FUNCTION__
,
NIPQUAD
(
fl
.
fl4_dst
),
NIPQUAD
(
fl
.
fl4_src
));
if
(
ip_route_output_key
(
&
rt
,
&
fl
))
{
SCTP_DEBUG_PRINTK
(
"sctp_v4_get_dst_mtu:ip_route_output_key"
" failed, returning %d as dst_mtu
\n
"
,
dst_mtu
);
}
else
{
dst_mtu
=
rt
->
u
.
dst
.
pmtu
;
SCTP_DEBUG_PRINTK
(
"sctp_v4_get_dst_mtu: "
"ip_route_output_key: dev:%s pmtu:%d
\n
"
,
rt
->
u
.
dst
.
dev
->
name
,
dst_mtu
);
ip_rt_put
(
rt
);
SCTP_DEBUG_PRINTK
(
"NO ROUTE
\n
"
);
return
NULL
;
}
return
dst_mtu
;
SCTP_DEBUG_PRINTK
(
"rt_dst:%u.%u.%u.%u, rt_src:%u.%u.%u.%u
\n
"
,
NIPQUAD
(
rt
->
rt_src
),
NIPQUAD
(
rt
->
rt_dst
));
return
&
rt
->
u
.
dst
;
}
/* Check if the dst entry's source addr matches the given source addr. */
int
sctp_v4_cmp_saddr
(
struct
dst_entry
*
dst
,
sockaddr_storage_t
*
saddr
)
{
struct
rtable
*
rt
=
(
struct
rtable
*
)
dst
;
return
(
rt
->
rt_src
==
saddr
->
v4
.
sin_addr
.
s_addr
);
}
/* Event handler for inet device events.
...
...
@@ -438,7 +452,8 @@ sctp_func_t sctp_ipv4_specific = {
.
queue_xmit
=
ip_queue_xmit
,
.
setsockopt
=
ip_setsockopt
,
.
getsockopt
=
ip_getsockopt
,
.
get_dst_mtu
=
sctp_v4_get_dst_mtu
,
.
get_dst
=
sctp_v4_get_dst
,
.
cmp_saddr
=
sctp_v4_cmp_saddr
,
.
net_header_len
=
sizeof
(
struct
iphdr
),
.
sockaddr_len
=
sizeof
(
struct
sockaddr_in
),
.
sa_family
=
AF_INET
,
...
...
net/sctp/sm_make_chunk.c
View file @
e8ece35b
...
...
@@ -1030,16 +1030,17 @@ sctp_chunk_t *sctp_chunkify(struct sk_buff *skb, const sctp_association_t *asoc,
return
retval
;
}
/* Set chunk->source based on the IP header in chunk->skb. */
void
sctp_init_
source
(
sctp_chunk_t
*
chunk
)
/* Set chunk->source
and dest
based on the IP header in chunk->skb. */
void
sctp_init_
addrs
(
sctp_chunk_t
*
chunk
)
{
sockaddr_storage_t
*
source
;
sockaddr_storage_t
*
source
,
*
dest
;
struct
sk_buff
*
skb
;
struct
sctphdr
*
sh
;
struct
iphdr
*
ih4
;
struct
ipv6hdr
*
ih6
;
source
=
&
chunk
->
source
;
dest
=
&
chunk
->
dest
;
skb
=
chunk
->
skb
;
ih4
=
skb
->
nh
.
iph
;
ih6
=
skb
->
nh
.
ipv6h
;
...
...
@@ -1050,6 +1051,9 @@ void sctp_init_source(sctp_chunk_t *chunk)
source
->
v4
.
sin_family
=
AF_INET
;
source
->
v4
.
sin_port
=
ntohs
(
sh
->
source
);
source
->
v4
.
sin_addr
.
s_addr
=
ih4
->
saddr
;
dest
->
v4
.
sin_family
=
AF_INET
;
dest
->
v4
.
sin_port
=
ntohs
(
sh
->
dest
);
dest
->
v4
.
sin_addr
.
s_addr
=
ih4
->
daddr
;
break
;
case
6
:
...
...
@@ -1057,6 +1061,9 @@ void sctp_init_source(sctp_chunk_t *chunk)
source
->
v6
.
sin6_family
=
AF_INET6
;
source
->
v6
.
sin6_port
=
ntohs
(
sh
->
source
);
source
->
v6
.
sin6_addr
=
ih6
->
saddr
;
dest
->
v6
.
sin6_family
=
AF_INET6
;
dest
->
v6
.
sin6_port
=
ntohs
(
sh
->
dest
);
dest
->
v6
.
sin6_addr
=
ih6
->
daddr
;
/* FIXME: What do we do with scope, etc. ? */
break
;
)
...
...
net/sctp/sm_statefuns.c
View file @
e8ece35b
...
...
@@ -4261,6 +4261,11 @@ sctp_packet_t *sctp_ootb_pkt_new(const sctp_association_t *asoc,
if
(
!
packet
)
goto
nomem_packet
;
/* Cache a route for the transport with the chunk's destination as
* the source address.
*/
sctp_transport_route
(
transport
,
(
sockaddr_storage_t
*
)
&
chunk
->
dest
);
packet
=
sctp_packet_init
(
packet
,
transport
,
sport
,
dport
);
packet
=
sctp_packet_config
(
packet
,
vtag
,
0
,
NULL
);
...
...
net/sctp/transport.c
View file @
e8ece35b
...
...
@@ -87,7 +87,6 @@ sctp_transport_t *sctp_transport_init(sctp_transport_t *peer,
peer
->
ipaddr
=
*
addr
;
peer
->
af_specific
=
sctp_get_af_specific
(
addr
);
peer
->
asoc
=
NULL
;
peer
->
pmtu
=
peer
->
af_specific
->
get_dst_mtu
(
addr
);
/* From 6.3.1 RTO Calculation:
*
...
...
@@ -161,6 +160,7 @@ void sctp_transport_destroy(sctp_transport_t *transport)
if
(
transport
->
asoc
)
sctp_association_put
(
transport
->
asoc
);
dst_release
(
transport
->
dst
);
kfree
(
transport
);
SCTP_DBG_OBJCNT_DEC
(
transport
);
}
...
...
@@ -200,6 +200,78 @@ void sctp_transport_set_owner(sctp_transport_t *transport,
sctp_association_hold
(
asoc
);
}
/* Caches the dst entry for a transport's destination address and an optional
* souce address.
*/
void
sctp_transport_route
(
sctp_transport_t
*
transport
,
sockaddr_storage_t
*
saddr
)
{
sctp_association_t
*
asoc
=
transport
->
asoc
;
sctp_func_t
*
af
=
transport
->
af_specific
;
sockaddr_storage_t
*
daddr
=
&
transport
->
ipaddr
;
sctp_bind_addr_t
*
bp
;
rwlock_t
*
addr_lock
;
struct
sockaddr_storage_list
*
laddr
;
struct
list_head
*
pos
;
struct
dst_entry
*
dst
;
dst
=
af
->
get_dst
(
daddr
,
saddr
);
/* If there is no association or if a source address is passed,
* no more validation is required.
*/
if
(
!
asoc
||
saddr
)
goto
out
;
if
(
SCTP_STATE_ESTABLISHED
==
asoc
->
state
)
{
bp
=
&
asoc
->
base
.
bind_addr
;
addr_lock
=
&
asoc
->
base
.
addr_lock
;
}
else
{
bp
=
&
asoc
->
ep
->
base
.
bind_addr
;
addr_lock
=
&
asoc
->
ep
->
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 dst.
*/
sctp_read_lock
(
addr_lock
);
list_for_each
(
pos
,
&
bp
->
address_list
)
{
laddr
=
list_entry
(
pos
,
struct
sockaddr_storage_list
,
list
);
if
(
af
->
cmp_saddr
(
dst
,
&
laddr
->
a
))
goto
out_unlock
;
}
sctp_read_unlock
(
addr_lock
);
/* None of the bound addresses match the source address of the
* dst. So release it.
*/
dst_release
(
dst
);
}
/* Walk through the bind address list and try to get a dst that
* matches a bind address as the source address.
*/
sctp_read_lock
(
addr_lock
);
list_for_each
(
pos
,
&
bp
->
address_list
)
{
laddr
=
list_entry
(
pos
,
struct
sockaddr_storage_list
,
list
);
dst
=
af
->
get_dst
(
daddr
,
&
laddr
->
a
);
if
(
dst
)
goto
out_unlock
;
}
out_unlock:
sctp_read_unlock
(
addr_lock
);
out:
transport
->
dst
=
dst
;
if
(
dst
)
transport
->
pmtu
=
dst
->
pmtu
;
else
transport
->
pmtu
=
SCTP_DEFAULT_MAXSEGMENT
;
}
/* Hold a reference to a transport. */
void
sctp_transport_hold
(
sctp_transport_t
*
transport
)
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment