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
Kirill Smelkov
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
Show 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