Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
L
linux-davinci-2.6.23
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Redmine
Redmine
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
linux
linux-davinci-2.6.23
Commits
1d8674ed
Commit
1d8674ed
authored
Sep 09, 2005
by
Linus Torvalds
Browse files
Options
Browse Files
Download
Plain Diff
Merge master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
parents
d99901d6
cb7b593c
Changes
11
Show whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
557 additions
and
555 deletions
+557
-555
include/linux/dccp.h
include/linux/dccp.h
+3
-0
net/dccp/ccids/ccid3.c
net/dccp/ccids/ccid3.c
+89
-74
net/dccp/ccids/ccid3.h
net/dccp/ccids/ccid3.h
+9
-5
net/dccp/ccids/lib/packet_history.h
net/dccp/ccids/lib/packet_history.h
+2
-1
net/dccp/dccp.h
net/dccp/dccp.h
+4
-12
net/dccp/input.c
net/dccp/input.c
+2
-2
net/dccp/ipv4.c
net/dccp/ipv4.c
+1
-0
net/dccp/minisocks.c
net/dccp/minisocks.c
+1
-0
net/dccp/options.c
net/dccp/options.c
+61
-29
net/ipv4/af_inet.c
net/ipv4/af_inet.c
+0
-13
net/ipv4/fib_trie.c
net/ipv4/fib_trie.c
+385
-419
No files found.
include/linux/dccp.h
View file @
1d8674ed
...
...
@@ -432,7 +432,10 @@ struct dccp_sock {
struct
ccid
*
dccps_hc_rx_ccid
;
struct
ccid
*
dccps_hc_tx_ccid
;
struct
dccp_options_received
dccps_options_received
;
struct
timeval
dccps_epoch
;
enum
dccp_role
dccps_role
:
2
;
__u8
dccps_hc_rx_insert_options
:
1
;
__u8
dccps_hc_tx_insert_options
:
1
;
};
static
inline
struct
dccp_sock
*
dccp_sk
(
const
struct
sock
*
sk
)
...
...
net/dccp/ccids/ccid3.c
View file @
1d8674ed
...
...
@@ -43,12 +43,22 @@
#include "ccid3.h"
/*
* Reason for maths with 10 here is to avoid 32 bit overflow when a is big.
* Reason for maths here is to avoid 32 bit overflow when a is big.
* With this we get close to the limit.
*/
static
inline
u32
usecs_div
(
const
u32
a
,
const
u32
b
)
{
const
u32
tmp
=
a
*
(
USEC_PER_SEC
/
10
);
return
b
>
20
?
tmp
/
(
b
/
10
)
:
tmp
;
const
u32
div
=
a
<
(
UINT_MAX
/
(
USEC_PER_SEC
/
10
))
?
10
:
a
<
(
UINT_MAX
/
(
USEC_PER_SEC
/
50
))
?
50
:
a
<
(
UINT_MAX
/
(
USEC_PER_SEC
/
100
))
?
100
:
a
<
(
UINT_MAX
/
(
USEC_PER_SEC
/
500
))
?
500
:
a
<
(
UINT_MAX
/
(
USEC_PER_SEC
/
1000
))
?
1000
:
a
<
(
UINT_MAX
/
(
USEC_PER_SEC
/
5000
))
?
5000
:
a
<
(
UINT_MAX
/
(
USEC_PER_SEC
/
10000
))
?
10000
:
a
<
(
UINT_MAX
/
(
USEC_PER_SEC
/
50000
))
?
50000
:
100000
;
const
u32
tmp
=
a
*
(
USEC_PER_SEC
/
div
);
return
(
b
>=
2
*
div
)
?
tmp
/
(
b
/
div
)
:
tmp
;
}
static
int
ccid3_debug
;
...
...
@@ -102,8 +112,7 @@ static const char *ccid3_tx_state_name(enum ccid3_hc_tx_states state)
static
inline
void
ccid3_hc_tx_set_state
(
struct
sock
*
sk
,
enum
ccid3_hc_tx_states
state
)
{
struct
dccp_sock
*
dp
=
dccp_sk
(
sk
);
struct
ccid3_hc_tx_sock
*
hctx
=
dp
->
dccps_hc_tx_ccid_private
;
struct
ccid3_hc_tx_sock
*
hctx
=
ccid3_hc_tx_sk
(
sk
);
enum
ccid3_hc_tx_states
oldstate
=
hctx
->
ccid3hctx_state
;
ccid3_pr_debug
(
"%s(%p) %-8.8s -> %s
\n
"
,
...
...
@@ -144,8 +153,7 @@ static inline void ccid3_calc_new_delta(struct ccid3_hc_tx_sock *hctx)
*/
static
void
ccid3_hc_tx_update_x
(
struct
sock
*
sk
)
{
struct
dccp_sock
*
dp
=
dccp_sk
(
sk
);
struct
ccid3_hc_tx_sock
*
hctx
=
dp
->
dccps_hc_tx_ccid_private
;
struct
ccid3_hc_tx_sock
*
hctx
=
ccid3_hc_tx_sk
(
sk
);
/* To avoid large error in calcX */
if
(
hctx
->
ccid3hctx_p
>=
TFRC_SMALLEST_P
)
{
...
...
@@ -159,7 +167,7 @@ static void ccid3_hc_tx_update_x(struct sock *sk)
}
else
{
struct
timeval
now
;
d
o_gettimeofday
(
&
now
);
d
ccp_timestamp
(
sk
,
&
now
);
if
(
timeval_delta
(
&
now
,
&
hctx
->
ccid3hctx_t_ld
)
>=
hctx
->
ccid3hctx_rtt
)
{
hctx
->
ccid3hctx_x
=
max_t
(
u32
,
min_t
(
u32
,
hctx
->
ccid3hctx_x_recv
,
...
...
@@ -174,9 +182,8 @@ static void ccid3_hc_tx_update_x(struct sock *sk)
static
void
ccid3_hc_tx_no_feedback_timer
(
unsigned
long
data
)
{
struct
sock
*
sk
=
(
struct
sock
*
)
data
;
struct
dccp_sock
*
dp
=
dccp_sk
(
sk
);
unsigned
long
next_tmout
=
0
;
struct
ccid3_hc_tx_sock
*
hctx
=
dp
->
dccps_hc_tx_ccid_private
;
struct
ccid3_hc_tx_sock
*
hctx
=
ccid3_hc_tx_sk
(
sk
)
;
bh_lock_sock
(
sk
);
if
(
sock_owned_by_user
(
sk
))
{
...
...
@@ -274,7 +281,7 @@ static int ccid3_hc_tx_send_packet(struct sock *sk,
struct
sk_buff
*
skb
,
int
len
)
{
struct
dccp_sock
*
dp
=
dccp_sk
(
sk
);
struct
ccid3_hc_tx_sock
*
hctx
=
dp
->
dccps_hc_tx_ccid_private
;
struct
ccid3_hc_tx_sock
*
hctx
=
ccid3_hc_tx_sk
(
sk
)
;
struct
dccp_tx_hist_entry
*
new_packet
;
struct
timeval
now
;
long
delay
;
...
...
@@ -307,7 +314,7 @@ static int ccid3_hc_tx_send_packet(struct sock *sk,
dccp_tx_hist_add_entry
(
&
hctx
->
ccid3hctx_hist
,
new_packet
);
}
d
o_gettimeofday
(
&
now
);
d
ccp_timestamp
(
sk
,
&
now
);
switch
(
hctx
->
ccid3hctx_state
)
{
case
TFRC_SSTATE_NO_SENT
:
...
...
@@ -348,18 +355,20 @@ static int ccid3_hc_tx_send_packet(struct sock *sk,
}
/* Can we send? if so add options and add to packet history */
if
(
rc
==
0
)
if
(
rc
==
0
)
{
dp
->
dccps_hc_tx_insert_options
=
1
;
new_packet
->
dccphtx_ccval
=
DCCP_SKB_CB
(
skb
)
->
dccpd_ccval
=
hctx
->
ccid3hctx_last_win_count
;
}
out:
return
rc
;
}
static
void
ccid3_hc_tx_packet_sent
(
struct
sock
*
sk
,
int
more
,
int
len
)
{
struct
dccp_sock
*
dp
=
dccp_sk
(
sk
);
struct
ccid3_hc_tx_sock
*
hctx
=
dp
->
dccps_hc_tx_ccid_private
;
const
struct
dccp_sock
*
dp
=
dccp_sk
(
sk
);
struct
ccid3_hc_tx_sock
*
hctx
=
ccid3_hc_tx_sk
(
sk
)
;
struct
timeval
now
;
BUG_ON
(
hctx
==
NULL
);
...
...
@@ -370,7 +379,7 @@ static void ccid3_hc_tx_packet_sent(struct sock *sk, int more, int len)
return
;
}
d
o_gettimeofday
(
&
now
);
d
ccp_timestamp
(
sk
,
&
now
);
/* check if we have sent a data packet */
if
(
len
>
0
)
{
...
...
@@ -445,10 +454,11 @@ static void ccid3_hc_tx_packet_sent(struct sock *sk, int more, int len)
static
void
ccid3_hc_tx_packet_recv
(
struct
sock
*
sk
,
struct
sk_buff
*
skb
)
{
struct
dccp_sock
*
dp
=
dccp_sk
(
sk
);
struct
ccid3_hc_tx_sock
*
hctx
=
dp
->
dccps_hc_tx_ccid_private
;
const
struct
dccp_sock
*
dp
=
dccp_sk
(
sk
);
struct
ccid3_hc_tx_sock
*
hctx
=
ccid3_hc_tx_sk
(
sk
)
;
struct
ccid3_options_received
*
opt_recv
;
struct
dccp_tx_hist_entry
*
packet
;
struct
timeval
now
;
unsigned
long
next_tmout
;
u32
t_elapsed
;
u32
pinv
;
...
...
@@ -471,7 +481,7 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
opt_recv
=
&
hctx
->
ccid3hctx_options_received
;
t_elapsed
=
dp
->
dccps_options_received
.
dccpor_elapsed_time
;
t_elapsed
=
dp
->
dccps_options_received
.
dccpor_elapsed_time
*
10
;
x_recv
=
opt_recv
->
ccid3or_receive_rate
;
pinv
=
opt_recv
->
ccid3or_loss_event_rate
;
...
...
@@ -496,9 +506,14 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
}
/* Update RTT */
r_sample
=
timeval_now_delta
(
&
packet
->
dccphtx_tstamp
);
/* FIXME: */
// r_sample -= usecs_to_jiffies(t_elapsed * 10);
dccp_timestamp
(
sk
,
&
now
);
r_sample
=
timeval_delta
(
&
now
,
&
packet
->
dccphtx_tstamp
);
if
(
unlikely
(
r_sample
<=
t_elapsed
))
LIMIT_NETDEBUG
(
KERN_WARNING
"%s: r_sample=%uus, t_elapsed=%uus
\n
"
,
__FUNCTION__
,
r_sample
,
t_elapsed
);
else
r_sample
-=
t_elapsed
;
/* Update RTT estimate by
* If (No feedback recv)
...
...
@@ -591,8 +606,7 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
static
void
ccid3_hc_tx_insert_options
(
struct
sock
*
sk
,
struct
sk_buff
*
skb
)
{
const
struct
dccp_sock
*
dp
=
dccp_sk
(
sk
);
struct
ccid3_hc_tx_sock
*
hctx
=
dp
->
dccps_hc_tx_ccid_private
;
struct
ccid3_hc_tx_sock
*
hctx
=
ccid3_hc_tx_sk
(
sk
);
if
(
hctx
==
NULL
||
!
(
sk
->
sk_state
==
DCCP_OPEN
||
sk
->
sk_state
==
DCCP_PARTOPEN
))
...
...
@@ -606,8 +620,8 @@ static int ccid3_hc_tx_parse_options(struct sock *sk, unsigned char option,
unsigned
char
*
value
)
{
int
rc
=
0
;
struct
dccp_sock
*
dp
=
dccp_sk
(
sk
);
struct
ccid3_hc_tx_sock
*
hctx
=
dp
->
dccps_hc_tx_ccid_private
;
const
struct
dccp_sock
*
dp
=
dccp_sk
(
sk
);
struct
ccid3_hc_tx_sock
*
hctx
=
ccid3_hc_tx_sk
(
sk
)
;
struct
ccid3_options_received
*
opt_recv
;
if
(
hctx
==
NULL
)
...
...
@@ -670,11 +684,11 @@ static int ccid3_hc_tx_init(struct sock *sk)
ccid3_pr_debug
(
"%s, sk=%p
\n
"
,
dccp_role
(
sk
),
sk
);
hctx
=
dp
->
dccps_hc_tx_ccid_private
=
kmalloc
(
sizeof
(
*
hctx
),
gfp_any
());
if
(
hctx
==
NULL
)
dp
->
dccps_hc_tx_ccid_private
=
kmalloc
(
sizeof
(
*
hctx
),
gfp_any
());
if
(
dp
->
dccps_hc_tx_ccid_private
==
NULL
)
return
-
ENOMEM
;
hctx
=
ccid3_hc_tx_sk
(
sk
);
memset
(
hctx
,
0
,
sizeof
(
*
hctx
));
if
(
dp
->
dccps_packet_size
>=
TFRC_MIN_PACKET_SIZE
&&
...
...
@@ -696,7 +710,7 @@ static int ccid3_hc_tx_init(struct sock *sk)
static
void
ccid3_hc_tx_exit
(
struct
sock
*
sk
)
{
struct
dccp_sock
*
dp
=
dccp_sk
(
sk
);
struct
ccid3_hc_tx_sock
*
hctx
=
dp
->
dccps_hc_tx_ccid_private
;
struct
ccid3_hc_tx_sock
*
hctx
=
ccid3_hc_tx_sk
(
sk
)
;
ccid3_pr_debug
(
"%s, sk=%p
\n
"
,
dccp_role
(
sk
),
sk
);
BUG_ON
(
hctx
==
NULL
);
...
...
@@ -738,8 +752,7 @@ static const char *ccid3_rx_state_name(enum ccid3_hc_rx_states state)
static
inline
void
ccid3_hc_rx_set_state
(
struct
sock
*
sk
,
enum
ccid3_hc_rx_states
state
)
{
struct
dccp_sock
*
dp
=
dccp_sk
(
sk
);
struct
ccid3_hc_rx_sock
*
hcrx
=
dp
->
dccps_hc_rx_ccid_private
;
struct
ccid3_hc_rx_sock
*
hcrx
=
ccid3_hc_rx_sk
(
sk
);
enum
ccid3_hc_rx_states
oldstate
=
hcrx
->
ccid3hcrx_state
;
ccid3_pr_debug
(
"%s(%p) %-8.8s -> %s
\n
"
,
...
...
@@ -751,14 +764,14 @@ static inline void ccid3_hc_rx_set_state(struct sock *sk,
static
void
ccid3_hc_rx_send_feedback
(
struct
sock
*
sk
)
{
struct
ccid3_hc_rx_sock
*
hcrx
=
ccid3_hc_rx_sk
(
sk
);
struct
dccp_sock
*
dp
=
dccp_sk
(
sk
);
struct
ccid3_hc_rx_sock
*
hcrx
=
dp
->
dccps_hc_rx_ccid_private
;
struct
dccp_rx_hist_entry
*
packet
;
struct
timeval
now
;
ccid3_pr_debug
(
"%s, sk=%p
\n
"
,
dccp_role
(
sk
),
sk
);
d
o_gettimeofday
(
&
now
);
d
ccp_timestamp
(
sk
,
&
now
);
switch
(
hcrx
->
ccid3hcrx_state
)
{
case
TFRC_RSTATE_NO_DATA
:
...
...
@@ -767,11 +780,8 @@ static void ccid3_hc_rx_send_feedback(struct sock *sk)
case
TFRC_RSTATE_DATA
:
{
const
u32
delta
=
timeval_delta
(
&
now
,
&
hcrx
->
ccid3hcrx_tstamp_last_feedback
);
hcrx
->
ccid3hcrx_x_recv
=
(
hcrx
->
ccid3hcrx_bytes_recv
*
USEC_PER_SEC
);
if
(
likely
(
delta
>
1
))
hcrx
->
ccid3hcrx_x_recv
/=
delta
;
hcrx
->
ccid3hcrx_x_recv
=
usecs_div
(
hcrx
->
ccid3hcrx_bytes_recv
,
delta
);
}
break
;
default:
...
...
@@ -801,14 +811,14 @@ static void ccid3_hc_rx_send_feedback(struct sock *sk)
hcrx
->
ccid3hcrx_pinv
=
~
0
;
else
hcrx
->
ccid3hcrx_pinv
=
1000000
/
hcrx
->
ccid3hcrx_p
;
dp
->
dccps_hc_rx_insert_options
=
1
;
dccp_send_ack
(
sk
);
}
static
void
ccid3_hc_rx_insert_options
(
struct
sock
*
sk
,
struct
sk_buff
*
skb
)
{
const
struct
dccp_sock
*
dp
=
dccp
_sk
(
sk
);
struct
ccid3_hc_rx_sock
*
hcrx
=
ccid3_hc_rx
_sk
(
sk
);
u32
x_recv
,
pinv
;
struct
ccid3_hc_rx_sock
*
hcrx
=
dp
->
dccps_hc_rx_ccid_private
;
if
(
hcrx
==
NULL
||
!
(
sk
->
sk_state
==
DCCP_OPEN
||
sk
->
sk_state
==
DCCP_PARTOPEN
))
...
...
@@ -837,8 +847,7 @@ static void ccid3_hc_rx_insert_options(struct sock *sk, struct sk_buff *skb)
static
u32
ccid3_hc_rx_calc_first_li
(
struct
sock
*
sk
)
{
struct
dccp_sock
*
dp
=
dccp_sk
(
sk
);
struct
ccid3_hc_rx_sock
*
hcrx
=
dp
->
dccps_hc_rx_ccid_private
;
struct
ccid3_hc_rx_sock
*
hcrx
=
ccid3_hc_rx_sk
(
sk
);
struct
dccp_rx_hist_entry
*
entry
,
*
next
,
*
tail
=
NULL
;
u32
rtt
,
delta
,
x_recv
,
fval
,
p
,
tmp2
;
struct
timeval
tstamp
=
{
0
,
};
...
...
@@ -889,10 +898,9 @@ found:
if
(
rtt
==
0
)
rtt
=
1
;
delta
=
timeval_now_delta
(
&
hcrx
->
ccid3hcrx_tstamp_last_feedback
);
x_recv
=
hcrx
->
ccid3hcrx_bytes_recv
*
USEC_PER_SEC
;
if
(
likely
(
delta
>
1
))
x_recv
/=
delta
;
dccp_timestamp
(
sk
,
&
tstamp
);
delta
=
timeval_delta
(
&
tstamp
,
&
hcrx
->
ccid3hcrx_tstamp_last_feedback
);
x_recv
=
usecs_div
(
hcrx
->
ccid3hcrx_bytes_recv
,
delta
);
tmp1
=
(
u64
)
x_recv
*
(
u64
)
rtt
;
do_div
(
tmp1
,
10000000
);
...
...
@@ -911,8 +919,7 @@ found:
static
void
ccid3_hc_rx_update_li
(
struct
sock
*
sk
,
u64
seq_loss
,
u8
win_loss
)
{
struct
dccp_sock
*
dp
=
dccp_sk
(
sk
);
struct
ccid3_hc_rx_sock
*
hcrx
=
dp
->
dccps_hc_rx_ccid_private
;
struct
ccid3_hc_rx_sock
*
hcrx
=
ccid3_hc_rx_sk
(
sk
);
if
(
seq_loss
!=
DCCP_MAX_SEQNO
+
1
&&
list_empty
(
&
hcrx
->
ccid3hcrx_li_hist
))
{
...
...
@@ -930,8 +937,7 @@ static void ccid3_hc_rx_update_li(struct sock *sk, u64 seq_loss, u8 win_loss)
static
void
ccid3_hc_rx_detect_loss
(
struct
sock
*
sk
)
{
struct
dccp_sock
*
dp
=
dccp_sk
(
sk
);
struct
ccid3_hc_rx_sock
*
hcrx
=
dp
->
dccps_hc_rx_ccid_private
;
struct
ccid3_hc_rx_sock
*
hcrx
=
ccid3_hc_rx_sk
(
sk
);
u8
win_loss
;
const
u64
seq_loss
=
dccp_rx_hist_detect_loss
(
&
hcrx
->
ccid3hcrx_hist
,
&
hcrx
->
ccid3hcrx_li_hist
,
...
...
@@ -942,13 +948,12 @@ static void ccid3_hc_rx_detect_loss(struct sock *sk)
static
void
ccid3_hc_rx_packet_recv
(
struct
sock
*
sk
,
struct
sk_buff
*
skb
)
{
struct
dccp_sock
*
dp
=
dccp_sk
(
sk
);
struct
ccid3_hc_rx_sock
*
hcrx
=
dp
->
dccps_hc_rx_ccid_private
;
struct
ccid3_hc_rx_sock
*
hcrx
=
ccid3_hc_rx_sk
(
sk
);
const
struct
dccp_options_received
*
opt_recv
;
struct
dccp_rx_hist_entry
*
packet
;
struct
timeval
now
;
u8
win_count
;
u32
p_prev
;
u32
p_prev
,
r_sample
,
t_elapsed
;
int
ins
;
if
(
hcrx
==
NULL
)
...
...
@@ -957,7 +962,7 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
BUG_ON
(
!
(
hcrx
->
ccid3hcrx_state
==
TFRC_RSTATE_NO_DATA
||
hcrx
->
ccid3hcrx_state
==
TFRC_RSTATE_DATA
));
opt_recv
=
&
d
p
->
dccps_options_received
;
opt_recv
=
&
d
ccp_sk
(
sk
)
->
dccps_options_received
;
switch
(
DCCP_SKB_CB
(
skb
)
->
dccpd_type
)
{
case
DCCP_PKT_ACK
:
...
...
@@ -967,10 +972,24 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
if
(
opt_recv
->
dccpor_timestamp_echo
==
0
)
break
;
p_prev
=
hcrx
->
ccid3hcrx_rtt
;
do_gettimeofday
(
&
now
);
hcrx
->
ccid3hcrx_rtt
=
timeval_usecs
(
&
now
)
-
(
opt_recv
->
dccpor_timestamp_echo
-
opt_recv
->
dccpor_elapsed_time
)
*
10
;
dccp_timestamp
(
sk
,
&
now
);
timeval_sub_usecs
(
&
now
,
opt_recv
->
dccpor_timestamp_echo
*
10
);
r_sample
=
timeval_usecs
(
&
now
);
t_elapsed
=
opt_recv
->
dccpor_elapsed_time
*
10
;
if
(
unlikely
(
r_sample
<=
t_elapsed
))
LIMIT_NETDEBUG
(
KERN_WARNING
"%s: r_sample=%uus, t_elapsed=%uus
\n
"
,
__FUNCTION__
,
r_sample
,
t_elapsed
);
else
r_sample
-=
t_elapsed
;
if
(
hcrx
->
ccid3hcrx_state
==
TFRC_RSTATE_NO_DATA
)
hcrx
->
ccid3hcrx_rtt
=
r_sample
;
else
hcrx
->
ccid3hcrx_rtt
=
(
hcrx
->
ccid3hcrx_rtt
*
9
)
/
10
+
r_sample
/
10
;
if
(
p_prev
!=
hcrx
->
ccid3hcrx_rtt
)
ccid3_pr_debug
(
"%s, New RTT=%luus, elapsed time=%u
\n
"
,
dccp_role
(
sk
),
hcrx
->
ccid3hcrx_rtt
,
...
...
@@ -985,7 +1004,7 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
return
;
}
packet
=
dccp_rx_hist_entry_new
(
ccid3_rx_hist
,
opt_recv
->
dccpor_ndp
,
packet
=
dccp_rx_hist_entry_new
(
ccid3_rx_hist
,
sk
,
opt_recv
->
dccpor_ndp
,
skb
,
SLAB_ATOMIC
);
if
(
packet
==
NULL
)
{
ccid3_pr_debug
(
"%s, sk=%p, Not enough mem to add rx packet "
...
...
@@ -1017,7 +1036,7 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
if
(
ins
!=
0
)
break
;
d
o_gettimeofday
(
&
now
);
d
ccp_timestamp
(
sk
,
&
now
);
if
(
timeval_delta
(
&
now
,
&
hcrx
->
ccid3hcrx_tstamp_last_ack
)
>=
hcrx
->
ccid3hcrx_rtt
)
{
hcrx
->
ccid3hcrx_tstamp_last_ack
=
now
;
...
...
@@ -1056,11 +1075,11 @@ static int ccid3_hc_rx_init(struct sock *sk)
ccid3_pr_debug
(
"%s, sk=%p
\n
"
,
dccp_role
(
sk
),
sk
);
hcrx
=
dp
->
dccps_hc_rx_ccid_private
=
kmalloc
(
sizeof
(
*
hcrx
),
gfp_any
());
if
(
hcrx
==
NULL
)
dp
->
dccps_hc_rx_ccid_private
=
kmalloc
(
sizeof
(
*
hcrx
),
gfp_any
());
if
(
dp
->
dccps_hc_rx_ccid_private
==
NULL
)
return
-
ENOMEM
;
hcrx
=
ccid3_hc_rx_sk
(
sk
);
memset
(
hcrx
,
0
,
sizeof
(
*
hcrx
));
if
(
dp
->
dccps_packet_size
>=
TFRC_MIN_PACKET_SIZE
&&
...
...
@@ -1072,18 +1091,16 @@ static int ccid3_hc_rx_init(struct sock *sk)
hcrx
->
ccid3hcrx_state
=
TFRC_RSTATE_NO_DATA
;
INIT_LIST_HEAD
(
&
hcrx
->
ccid3hcrx_hist
);
INIT_LIST_HEAD
(
&
hcrx
->
ccid3hcrx_li_hist
);
/*
* XXX this seems to be paranoid, need to think more about this, for
* now start with something different than zero. -acme
*/
hcrx
->
ccid3hcrx_rtt
=
USEC_PER_SEC
/
5
;
dccp_timestamp
(
sk
,
&
hcrx
->
ccid3hcrx_tstamp_last_ack
);
hcrx
->
ccid3hcrx_tstamp_last_feedback
=
hcrx
->
ccid3hcrx_tstamp_last_ack
;
hcrx
->
ccid3hcrx_rtt
=
5000
;
/* XXX 5ms for now... */
return
0
;
}
static
void
ccid3_hc_rx_exit
(
struct
sock
*
sk
)
{
struct
ccid3_hc_rx_sock
*
hcrx
=
ccid3_hc_rx_sk
(
sk
);
struct
dccp_sock
*
dp
=
dccp_sk
(
sk
);
struct
ccid3_hc_rx_sock
*
hcrx
=
dp
->
dccps_hc_rx_ccid_private
;
ccid3_pr_debug
(
"%s, sk=%p
\n
"
,
dccp_role
(
sk
),
sk
);
...
...
@@ -1104,8 +1121,7 @@ static void ccid3_hc_rx_exit(struct sock *sk)
static
void
ccid3_hc_rx_get_info
(
struct
sock
*
sk
,
struct
tcp_info
*
info
)
{
const
struct
dccp_sock
*
dp
=
dccp_sk
(
sk
);
const
struct
ccid3_hc_rx_sock
*
hcrx
=
dp
->
dccps_hc_rx_ccid_private
;
const
struct
ccid3_hc_rx_sock
*
hcrx
=
ccid3_hc_rx_sk
(
sk
);
if
(
hcrx
==
NULL
)
return
;
...
...
@@ -1117,8 +1133,7 @@ static void ccid3_hc_rx_get_info(struct sock *sk, struct tcp_info *info)
static
void
ccid3_hc_tx_get_info
(
struct
sock
*
sk
,
struct
tcp_info
*
info
)
{
const
struct
dccp_sock
*
dp
=
dccp_sk
(
sk
);
const
struct
ccid3_hc_tx_sock
*
hctx
=
dp
->
dccps_hc_tx_ccid_private
;
const
struct
ccid3_hc_tx_sock
*
hctx
=
ccid3_hc_tx_sk
(
sk
);
if
(
hctx
==
NULL
)
return
;
...
...
net/dccp/ccids/ccid3.h
View file @
1d8674ed
...
...
@@ -115,7 +115,7 @@ struct ccid3_hc_rx_sock {
u64
ccid3hcrx_seqno_last_counter
:
48
,
ccid3hcrx_state:
8
,
ccid3hcrx_last_counter:
4
;
u
nsigned
long
ccid3hcrx_rtt
;
u
32
ccid3hcrx_rtt
;
u32
ccid3hcrx_p
;
u32
ccid3hcrx_bytes_recv
;
struct
timeval
ccid3hcrx_tstamp_last_feedback
;
...
...
@@ -128,10 +128,14 @@ struct ccid3_hc_rx_sock {
u32
ccid3hcrx_x_recv
;
};
#define ccid3_hc_tx_field(s,field) (s->dccps_hc_tx_ccid_private == NULL ? 0 : \
((struct ccid3_hc_tx_sock *)s->dccps_hc_tx_ccid_private)->ccid3hctx_##field)
static
inline
struct
ccid3_hc_tx_sock
*
ccid3_hc_tx_sk
(
const
struct
sock
*
sk
)
{
return
dccp_sk
(
sk
)
->
dccps_hc_tx_ccid_private
;
}
#define ccid3_hc_rx_field(s,field) (s->dccps_hc_rx_ccid_private == NULL ? 0 : \
((struct ccid3_hc_rx_sock *)s->dccps_hc_rx_ccid_private)->ccid3hcrx_##field)
static
inline
struct
ccid3_hc_rx_sock
*
ccid3_hc_rx_sk
(
const
struct
sock
*
sk
)
{
return
dccp_sk
(
sk
)
->
dccps_hc_rx_ccid_private
;
}
#endif
/* _DCCP_CCID3_H_ */
net/dccp/ccids/lib/packet_history.h
View file @
1d8674ed
...
...
@@ -134,6 +134,7 @@ static inline struct dccp_tx_hist_entry *
static
inline
struct
dccp_rx_hist_entry
*
dccp_rx_hist_entry_new
(
struct
dccp_rx_hist
*
hist
,
const
struct
sock
*
sk
,
const
u32
ndp
,
const
struct
sk_buff
*
skb
,
const
unsigned
int
__nocast
prio
)
...
...
@@ -148,7 +149,7 @@ static inline struct dccp_rx_hist_entry *
entry
->
dccphrx_ccval
=
dh
->
dccph_ccval
;
entry
->
dccphrx_type
=
dh
->
dccph_type
;
entry
->
dccphrx_ndp
=
ndp
;
d
o_gettimeofday
(
&
(
entry
->
dccphrx_tstamp
)
);
d
ccp_timestamp
(
sk
,
&
entry
->
dccphrx_tstamp
);
}
return
entry
;
...
...
net/dccp/dccp.h
View file @
1d8674ed
...
...
@@ -426,10 +426,13 @@ extern struct dccp_ackpkts *
dccp_ackpkts_alloc
(
unsigned
int
len
,
const
unsigned
int
__nocast
priority
);
extern
void
dccp_ackpkts_free
(
struct
dccp_ackpkts
*
ap
);
extern
int
dccp_ackpkts_add
(
struct
dccp_ackpkts
*
ap
,
u64
ackno
,
u8
state
);
extern
int
dccp_ackpkts_add
(
struct
dccp_ackpkts
*
ap
,
const
struct
sock
*
sk
,
u64
ackno
,
u8
state
);
extern
void
dccp_ackpkts_check_rcv_ackno
(
struct
dccp_ackpkts
*
ap
,
struct
sock
*
sk
,
u64
ackno
);
extern
void
dccp_timestamp
(
const
struct
sock
*
sk
,
struct
timeval
*
tv
);
static
inline
suseconds_t
timeval_usecs
(
const
struct
timeval
*
tv
)
{
return
tv
->
tv_sec
*
USEC_PER_SEC
+
tv
->
tv_usec
;
...
...
@@ -468,17 +471,6 @@ static inline void timeval_sub_usecs(struct timeval *tv,
}
}
/*
* Returns the difference in usecs between timeval
* passed in and current time
*/
static
inline
suseconds_t
timeval_now_delta
(
const
struct
timeval
*
tv
)
{
struct
timeval
now
;
do_gettimeofday
(
&
now
);
return
timeval_delta
(
&
now
,
tv
);
}
#ifdef CONFIG_IP_DCCP_DEBUG
extern
void
dccp_ackvector_print
(
const
u64
ackno
,
const
unsigned
char
*
vector
,
int
len
);
...
...
net/dccp/input.c
View file @
1d8674ed
...
...
@@ -170,7 +170,7 @@ int dccp_rcv_established(struct sock *sk, struct sk_buff *skb,
if
(
dp
->
dccps_options
.
dccpo_send_ack_vector
)
{
struct
dccp_ackpkts
*
ap
=
dp
->
dccps_hc_rx_ackpkts
;
if
(
dccp_ackpkts_add
(
dp
->
dccps_hc_rx_ackpkts
,
if
(
dccp_ackpkts_add
(
dp
->
dccps_hc_rx_ackpkts
,
sk
,
DCCP_SKB_CB
(
skb
)
->
dccpd_seq
,
DCCP_ACKPKTS_STATE_RECEIVED
))
{
LIMIT_NETDEBUG
(
KERN_WARNING
"DCCP: acknowledgeable "
...
...
@@ -498,7 +498,7 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
* DCCP_ACKPKTS_STATE_ECN_MARKED
*/
if
(
dp
->
dccps_options
.
dccpo_send_ack_vector
)
{
if
(
dccp_ackpkts_add
(
dp
->
dccps_hc_rx_ackpkts
,
if
(
dccp_ackpkts_add
(
dp
->
dccps_hc_rx_ackpkts
,
sk
,
DCCP_SKB_CB
(
skb
)
->
dccpd_seq
,
DCCP_ACKPKTS_STATE_RECEIVED
))
goto
discard
;
...
...
net/dccp/ipv4.c
View file @
1d8674ed
...
...
@@ -1243,6 +1243,7 @@ static int dccp_v4_init_sock(struct sock *sk)
static
int
dccp_ctl_socket_init
=
1
;
dccp_options_init
(
&
dp
->
dccps_options
);
do_gettimeofday
(
&
dp
->
dccps_epoch
);
if
(
dp
->
dccps_options
.
dccpo_send_ack_vector
)
{
dp
->
dccps_hc_rx_ackpkts
=
...
...
net/dccp/minisocks.c
View file @
1d8674ed
...
...
@@ -96,6 +96,7 @@ struct sock *dccp_create_openreq_child(struct sock *sk,
newdp
->
dccps_hc_rx_ackpkts
=
NULL
;
newdp
->
dccps_role
=
DCCP_ROLE_SERVER
;
newicsk
->
icsk_rto
=
DCCP_TIMEOUT_INIT
;
do_gettimeofday
(
&
newdp
->
dccps_epoch
);
if
(
newdp
->
dccps_options
.
dccpo_send_ack_vector
)
{
newdp
->
dccps_hc_rx_ackpkts
=
...
...
net/dccp/options.c
View file @
1d8674ed
...
...
@@ -72,6 +72,7 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb)
struct
dccp_options_received
*
opt_recv
=
&
dp
->
dccps_options_received
;
unsigned
char
opt
,
len
;
unsigned
char
*
value
;
u32
elapsed_time
;
memset
(
opt_recv
,
0
,
sizeof
(
*
opt_recv
));
...
...
@@ -139,7 +140,7 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb)
opt_recv
->
dccpor_timestamp
=
ntohl
(
*
(
u32
*
)
value
);
dp
->
dccps_timestamp_echo
=
opt_recv
->
dccpor_timestamp
;
d
o_gettimeofday
(
&
dp
->
dccps_timestamp_time
);
d
ccp_timestamp
(
sk
,
&
dp
->
dccps_timestamp_time
);
dccp_pr_debug
(
"%sTIMESTAMP=%u, ackno=%llu
\n
"
,
debug_prefix
,
opt_recv
->
dccpor_timestamp
,
...
...
@@ -159,18 +160,18 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb)
(
unsigned
long
long
)
DCCP_SKB_CB
(
skb
)
->
dccpd_ack_seq
);
if
(
len
>
4
)
{
if
(
len
==
4
)
break
;
if
(
len
==
6
)
opt_recv
->
dccpor_elapsed_time
=
ntohs
(
*
(
u16
*
)(
value
+
4
));
elapsed_time
=
ntohs
(
*
(
u16
*
)(
value
+
4
));
else
opt_recv
->
dccpor_elapsed_time
=
ntohl
(
*
(
u32
*
)(
value
+
4
));
elapsed_time
=
ntohl
(
*
(
u32
*
)(
value
+
4
));
dccp_pr_debug
(
"%sTIMESTAMP_ECHO ELAPSED_TIME=%d
\n
"
,
debug_prefix
,
opt_recv
->
dccpor_elapsed_time
);
}
/* Give precedence to the biggest ELAPSED_TIME */
if
(
elapsed_time
>
opt_recv
->
dccpor_elapsed_time
)
opt_recv
->
dccpor_elapsed_time
=
elapsed_time
;
break
;
case
DCCPO_ELAPSED_TIME
:
if
(
len
!=
2
&&
len
!=
4
)
...
...
@@ -180,14 +181,15 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb)
continue
;
if
(
len
==
2
)
opt_recv
->
dccpor_elapsed_time
=
ntohs
(
*
(
u16
*
)
value
);
elapsed_time
=
ntohs
(
*
(
u16
*
)
value
);
else
opt_recv
->
dccpor_elapsed_time
=
ntohl
(
*
(
u32
*
)
value
);
elapsed_time
=
ntohl
(
*
(
u32
*
)
value
);
if
(
elapsed_time
>
opt_recv
->
dccpor_elapsed_time
)
opt_recv
->
dccpor_elapsed_time
=
elapsed_time
;
dccp_pr_debug
(
"%sELAPSED_TIME=%d
\n
"
,
debug_prefix
,
opt_recv
->
dccpor_
elapsed_time
);
elapsed_time
);
break
;
/*
* From draft-ietf-dccp-spec-11.txt:
...
...
@@ -359,9 +361,13 @@ static void dccp_insert_option_ack_vector(struct sock *sk, struct sk_buff *skb)
#endif
struct
dccp_ackpkts
*
ap
=
dp
->
dccps_hc_rx_ackpkts
;
int
len
=
ap
->
dccpap_buf_vector_len
+
2
;
const
u32
elapsed_time
=
timeval_now_delta
(
&
ap
->
dccpap_time
)
/
10
;
struct
timeval
now
;
u32
elapsed_time
;
unsigned
char
*
to
,
*
from
;
dccp_timestamp
(
sk
,
&
now
);
elapsed_time
=
timeval_delta
(
&
now
,
&
ap
->
dccpap_time
)
/
10
;
if
(
elapsed_time
!=
0
)
dccp_insert_option_elapsed_time
(
sk
,
skb
,
elapsed_time
);
...
...
@@ -426,13 +432,29 @@ static void dccp_insert_option_ack_vector(struct sock *sk, struct sk_buff *skb)
(
unsigned
long
long
)
ap
->
dccpap_ack_ackno
);
}
void
dccp_timestamp
(
const
struct
sock
*
sk
,
struct
timeval
*
tv
)
{
const
struct
dccp_sock
*
dp
=
dccp_sk
(
sk
);
do_gettimeofday
(
tv
);
tv
->
tv_sec
-=
dp
->
dccps_epoch
.
tv_sec
;
tv
->
tv_usec
-=
dp
->
dccps_epoch
.
tv_usec
;
while
(
tv
->
tv_usec
<
0
)
{
tv
->
tv_sec
--
;
tv
->
tv_usec
+=
USEC_PER_SEC
;
}
}
EXPORT_SYMBOL_GPL
(
dccp_timestamp
);
void
dccp_insert_option_timestamp
(
struct
sock
*
sk
,
struct
sk_buff
*
skb
)
{
struct
timeval
tv
;
u32
now
;
d
o_gettimeofday
(
&
tv
);
now
=
(
tv
.
tv_sec
*
USEC_PER_SEC
+
tv
.
tv_usec
)
/
10
;
d
ccp_timestamp
(
sk
,
&
tv
);
now
=
timeval_usecs
(
&
tv
)
/
10
;
/* yes this will overflow but that is the point as we want a
* 10 usec 32 bit timer which mean it wraps every 11.9 hours */
...
...
@@ -450,13 +472,17 @@ static void dccp_insert_option_timestamp_echo(struct sock *sk,
const
char
*
debug_prefix
=
dp
->
dccps_role
==
DCCP_ROLE_CLIENT
?
"CLIENT TX opt: "
:
"server TX opt: "
;
#endif
struct
timeval
now
;
u32
tstamp_echo
;
const
u32
elapsed_time
=
timeval_now_delta
(
&
dp
->
dccps_timestamp_time
)
/
10
;
const
int
elapsed_time_len
=
dccp_elapsed_time_len
(
elapsed_time
);
const
int
len
=
6
+
elapsed_time_len
;
u32
elapsed_time
;
int
len
,
elapsed_time_len
;
unsigned
char
*
to
;
dccp_timestamp
(
sk
,
&
now
);
elapsed_time
=
timeval_delta
(
&
now
,
&
dp
->
dccps_timestamp_time
)
/
10
;
elapsed_time_len
=
dccp_elapsed_time_len
(
elapsed_time
);
len
=
6
+
elapsed_time_len
;
if
(
DCCP_SKB_CB
(
skb
)
->
dccpd_opt_len
+
len
>
DCCP_MAX_OPT_LEN
)
{
LIMIT_NETDEBUG
(
KERN_INFO
"DCCP: packet too small to insert "
"timestamp echo!
\n
"
);
...
...
@@ -505,13 +531,18 @@ void dccp_insert_options(struct sock *sk, struct sk_buff *skb)
(
dp
->
dccps_hc_rx_ackpkts
->
dccpap_buf_ackno
!=
DCCP_MAX_SEQNO
+
1
))
dccp_insert_option_ack_vector
(
sk
,
skb
);
if
(
dp
->
dccps_timestamp_echo
!=
0
)
dccp_insert_option_timestamp_echo
(
sk
,
skb
);
}
if
(
dp
->
dccps_hc_rx_insert_options
)
{
ccid_hc_rx_insert_options
(
dp
->
dccps_hc_rx_ccid
,
sk
,
skb
);
dp
->
dccps_hc_rx_insert_options
=
0
;
}
if
(
dp
->
dccps_hc_tx_insert_options
)
{
ccid_hc_tx_insert_options
(
dp
->
dccps_hc_tx_ccid
,
sk
,
skb
);
dp
->
dccps_hc_tx_insert_options
=
0
;
}
/* XXX: insert other options when appropriate */
...
...
@@ -616,7 +647,8 @@ static inline int dccp_ackpkts_set_buf_head_state(struct dccp_ackpkts *ap,
/*
* Implements the draft-ietf-dccp-spec-11.txt Appendix A
*/
int
dccp_ackpkts_add
(
struct
dccp_ackpkts
*
ap
,
u64
ackno
,
u8
state
)
int
dccp_ackpkts_add
(
struct
dccp_ackpkts
*
ap
,
const
struct
sock
*
sk
,
u64
ackno
,
u8
state
)
{
/*
* Check at the right places if the buffer is full, if it is, tell the
...
...
@@ -697,7 +729,7 @@ int dccp_ackpkts_add(struct dccp_ackpkts *ap, u64 ackno, u8 state)
}
ap
->
dccpap_buf_ackno
=
ackno
;
d
o_gettimeofday
(
&
ap
->
dccpap_time
);
d
ccp_timestamp
(
sk
,
&
ap
->
dccpap_time
);
out:
dccp_pr_debug
(
""
);
dccp_ackpkts_print
(
ap
);
...
...
net/ipv4/af_inet.c
View file @
1d8674ed
...
...
@@ -1248,11 +1248,6 @@ module_init(inet_init);
/* ------------------------------------------------------------------------ */
#ifdef CONFIG_PROC_FS
#ifdef CONFIG_IP_FIB_TRIE
extern
int
fib_stat_proc_init
(
void
);
extern
void
fib_stat_proc_exit
(
void
);
#endif
static
int
__init
ipv4_proc_init
(
void
)
{
int
rc
=
0
;
...
...
@@ -1265,19 +1260,11 @@ static int __init ipv4_proc_init(void)
goto
out_udp
;
if
(
fib_proc_init
())
goto
out_fib
;
#ifdef CONFIG_IP_FIB_TRIE
if
(
fib_stat_proc_init
())
goto
out_fib_stat
;
#endif
if
(
ip_misc_proc_init
())
goto
out_misc
;
out:
return
rc
;
out_misc:
#ifdef CONFIG_IP_FIB_TRIE
fib_stat_proc_exit
();
out_fib_stat:
#endif
fib_proc_exit
();
out_fib:
udp4_proc_exit
();
...
...
net/ipv4/fib_trie.c
View file @
1d8674ed
...
...
@@ -43,7 +43,7 @@
* 2 of the License, or (at your option) any later version.
*/
#define VERSION "0.40
2
"
#define VERSION "0.40
3
"
#include <linux/config.h>
#include <asm/uaccess.h>
...
...
@@ -164,7 +164,6 @@ static struct node *resize(struct trie *t, struct tnode *tn);
static
struct
tnode
*
inflate
(
struct
trie
*
t
,
struct
tnode
*
tn
);
static
struct
tnode
*
halve
(
struct
trie
*
t
,
struct
tnode
*
tn
);
static
void
tnode_free
(
struct
tnode
*
tn
);
static
void
trie_dump_seq
(
struct
seq_file
*
seq
,
struct
trie
*
t
);
static
kmem_cache_t
*
fn_alias_kmem
__read_mostly
;
static
struct
trie
*
trie_local
=
NULL
,
*
trie_main
=
NULL
;
...
...
@@ -1971,378 +1970,137 @@ struct fib_table * __init fib_hash_init(int id)
return
tb
;
}
/* Trie dump functions */
static
void
putspace_seq
(
struct
seq_file
*
seq
,
int
n
)
{
while
(
n
--
)
seq_printf
(
seq
,
" "
);
}
#ifdef CONFIG_PROC_FS
/* Depth first Trie walk iterator */
struct
fib_trie_iter
{
struct
tnode
*
tnode
;
struct
trie
*
trie
;
unsigned
index
;
unsigned
depth
;
};
static
void
printbin_seq
(
struct
seq_file
*
seq
,
unsigned
int
v
,
int
bits
)
static
struct
node
*
fib_trie_get_next
(
struct
fib_trie_iter
*
iter
)
{
while
(
bits
--
)
seq_printf
(
seq
,
"%s"
,
(
v
&
(
1
<<
bits
))
?
"1"
:
"0"
)
;
}
struct
tnode
*
tn
=
iter
->
tnode
;
unsigned
cindex
=
iter
->
index
;
struct
tnode
*
p
;
static
void
printnode_seq
(
struct
seq_file
*
seq
,
int
indent
,
struct
node
*
n
,
int
pend
,
int
cindex
,
int
bits
)
{
putspace_seq
(
seq
,
indent
);
if
(
IS_LEAF
(
n
))
seq_printf
(
seq
,
"|"
);
else
seq_printf
(
seq
,
"+"
);
if
(
bits
)
{
seq_printf
(
seq
,
"%d/"
,
cindex
);
printbin_seq
(
seq
,
cindex
,
bits
);
seq_printf
(
seq
,
": "
);
}
else
seq_printf
(
seq
,
"<root>: "
);
seq_printf
(
seq
,
"%s:%p "
,
IS_LEAF
(
n
)
?
"Leaf"
:
"Internal node"
,
n
);
pr_debug
(
"get_next iter={node=%p index=%d depth=%d}
\n
"
,
iter
->
tnode
,
iter
->
index
,
iter
->
depth
);
rescan:
while
(
cindex
<
(
1
<<
tn
->
bits
))
{
struct
node
*
n
=
tnode_get_child
(
tn
,
cindex
);
if
(
n
)
{
if
(
IS_LEAF
(
n
))
{
struct
leaf
*
l
=
(
struct
leaf
*
)
n
;
struct
fib_alias
*
fa
;
int
i
;
seq_printf
(
seq
,
"key=%d.%d.%d.%d
\n
"
,
n
->
key
>>
24
,
(
n
->
key
>>
16
)
%
256
,
(
n
->
key
>>
8
)
%
256
,
n
->
key
%
256
);
for
(
i
=
32
;
i
>=
0
;
i
--
)
if
(
find_leaf_info
(
&
l
->
list
,
i
))
{
struct
list_head
*
fa_head
=
get_fa_head
(
l
,
i
);
if
(
!
fa_head
)
continue
;
if
(
list_empty
(
fa_head
))
continue
;
putspace_seq
(
seq
,
indent
+
2
);
seq_printf
(
seq
,
"{/%d...dumping}
\n
"
,
i
);
list_for_each_entry_rcu
(
fa
,
fa_head
,
fa_list
)
{
putspace_seq
(
seq
,
indent
+
2
);
if
(
fa
->
fa_info
==
NULL
)
{
seq_printf
(
seq
,
"Error fa_info=NULL
\n
"
);
continue
;
}
if
(
fa
->
fa_info
->
fib_nh
==
NULL
)
{
seq_printf
(
seq
,
"Error _fib_nh=NULL
\n
"
);
continue
;
}
seq_printf
(
seq
,
"{type=%d scope=%d TOS=%d}
\n
"
,
fa
->
fa_type
,
fa
->
fa_scope
,
fa
->
fa_tos
);
}
}
iter
->
tnode
=
tn
;
iter
->
index
=
cindex
+
1
;
}
else
{
struct
tnode
*
tn
=
(
struct
tnode
*
)
n
;
int
plen
=
((
struct
tnode
*
)
n
)
->
pos
;
t_key
prf
=
MASK_PFX
(
n
->
key
,
plen
);
seq_printf
(
seq
,
"key=%d.%d.%d.%d/%d
\n
"
,
prf
>>
24
,
(
prf
>>
16
)
%
256
,
(
prf
>>
8
)
%
256
,
prf
%
256
,
plen
);
putspace_seq
(
seq
,
indent
);
seq_printf
(
seq
,
"| "
);
seq_printf
(
seq
,
"{key prefix=%08x/"
,
tn
->
key
&
TKEY_GET_MASK
(
0
,
tn
->
pos
));
printbin_seq
(
seq
,
tkey_extract_bits
(
tn
->
key
,
0
,
tn
->
pos
),
tn
->
pos
);
seq_printf
(
seq
,
"}
\n
"
);
putspace_seq
(
seq
,
indent
);
seq_printf
(
seq
,
"| "
);
seq_printf
(
seq
,
"{pos=%d"
,
tn
->
pos
);
seq_printf
(
seq
,
" (skip=%d bits)"
,
tn
->
pos
-
pend
);
seq_printf
(
seq
,
" bits=%d (%u children)}
\n
"
,
tn
->
bits
,
(
1
<<
tn
->
bits
));
putspace_seq
(
seq
,
indent
);
seq_printf
(
seq
,
"| "
);
seq_printf
(
seq
,
"{empty=%d full=%d}
\n
"
,
tn
->
empty_children
,
tn
->
full_children
);
}
}
static
void
trie_dump_seq
(
struct
seq_file
*
seq
,
struct
trie
*
t
)
{
struct
node
*
n
;
int
cindex
=
0
;
int
indent
=
1
;
int
pend
=
0
;
int
depth
=
0
;
struct
tnode
*
tn
;
rcu_read_lock
();
n
=
rcu_dereference
(
t
->
trie
);
seq_printf
(
seq
,
"------ trie_dump of t=%p ------
\n
"
,
t
);
if
(
!
n
)
{
seq_printf
(
seq
,
"------ trie is empty
\n
"
);
rcu_read_unlock
();
return
;
/* push down one level */
iter
->
tnode
=
(
struct
tnode
*
)
n
;
iter
->
index
=
0
;
++
iter
->
depth
;
}
printnode_seq
(
seq
,
indent
,
n
,
pend
,
cindex
,
0
);
if
(
!
IS_TNODE
(
n
))
{
rcu_read_unlock
();
return
;
return
n
;
}
tn
=
(
struct
tnode
*
)
n
;
pend
=
tn
->
pos
+
tn
->
bits
;
putspace_seq
(
seq
,
indent
);
seq_printf
(
seq
,
"
\\
--
\n
"
);
indent
+=
3
;
depth
++
;
while
(
tn
&&
cindex
<
(
1
<<
tn
->
bits
))
{
struct
node
*
child
=
rcu_dereference
(
tn
->
child
[
cindex
]);
if
(
!
child
)
cindex
++
;
else
{
/* Got a child */
printnode_seq
(
seq
,
indent
,
child
,
pend
,
cindex
,
tn
->
bits
);
if
(
IS_LEAF
(
child
))
cindex
++
;
else
{
/*
* New tnode. Decend one level
*/
depth
++
;
n
=
child
;
tn
=
(
struct
tnode
*
)
n
;
pend
=
tn
->
pos
+
tn
->
bits
;
putspace_seq
(
seq
,
indent
);
seq_printf
(
seq
,
"
\\
--
\n
"
);
indent
+=
3
;
cindex
=
0
;
}
++
cindex
;
}
/*
* Test if we are done
*/
while
(
cindex
>=
(
1
<<
tn
->
bits
))
{
/*
* Move upwards and test for root
* pop off all traversed nodes
*/
if
(
NODE_PARENT
(
tn
)
==
NULL
)
{
tn
=
NULL
;
break
;
/* Current node exhausted, pop back up */
p
=
NODE_PARENT
(
tn
);
if
(
p
)
{
cindex
=
tkey_extract_bits
(
tn
->
key
,
p
->
pos
,
p
->
bits
)
+
1
;
tn
=
p
;
--
iter
->
depth
;
goto
rescan
;
}
cindex
=
tkey_extract_bits
(
tn
->
key
,
NODE_PARENT
(
tn
)
->
pos
,
NODE_PARENT
(
tn
)
->
bits
);
cindex
++
;
tn
=
NODE_PARENT
(
tn
);
pend
=
tn
->
pos
+
tn
->
bits
;
indent
-=
3
;
depth
--
;
}
}
rcu_read_unlock
();
/* got root? */
return
NULL
;
}
static
struct
trie_stat
*
trie_stat_new
(
void
)
static
struct
node
*
fib_trie_get_first
(
struct
fib_trie_iter
*
iter
,
struct
trie
*
t
)
{
struct
trie_stat
*
s
;
int
i
;
struct
node
*
n
=
rcu_dereference
(
t
->
trie
);
s
=
kmalloc
(
sizeof
(
struct
trie_stat
),
GFP_KERNEL
);
if
(
!
s
)
if
(
n
&&
IS_TNODE
(
n
))
{
iter
->
tnode
=
(
struct
tnode
*
)
n
;
iter
->
trie
=
t
;
iter
->
index
=
0
;
iter
->
depth
=
0
;
return
n
;
}
return
NULL
;
s
->
totdepth
=
0
;
s
->
maxdepth
=
0
;
s
->
tnodes
=
0
;
s
->
leaves
=
0
;
s
->
nullpointers
=
0
;
for
(
i
=
0
;
i
<
MAX_CHILDS
;
i
++
)
s
->
nodesizes
[
i
]
=
0
;
return
s
;
}
static
struct
trie_stat
*
trie_collect_stats
(
struct
trie
*
t
)
static
void
trie_collect_stats
(
struct
trie
*
t
,
struct
trie_stat
*
s
)
{
struct
node
*
n
;
struct
trie_stat
*
s
=
trie_stat_new
();
int
cindex
=
0
;
int
pend
=
0
;
int
depth
=
0
;
struct
fib_trie_iter
iter
;
if
(
!
s
)
return
NULL
;
memset
(
s
,
0
,
sizeof
(
*
s
));
rcu_read_lock
();
n
=
rcu_dereference
(
t
->
trie
);
if
(
!
n
)
return
s
;
if
(
IS_TNODE
(
n
))
{
struct
tnode
*
tn
=
(
struct
tnode
*
)
n
;
pend
=
tn
->
pos
+
tn
->
bits
;
s
->
nodesizes
[
tn
->
bits
]
++
;
depth
++
;
while
(
tn
&&
cindex
<
(
1
<<
tn
->
bits
))
{
struct
node
*
ch
=
rcu_dereference
(
tn
->
child
[
cindex
]);
if
(
ch
)
{
/* Got a child */
if
(
IS_LEAF
(
tn
->
child
[
cindex
]))
{
cindex
++
;
/* stats */
if
(
depth
>
s
->
maxdepth
)
s
->
maxdepth
=
depth
;
s
->
totdepth
+=
depth
;
for
(
n
=
fib_trie_get_first
(
&
iter
,
t
);
n
;
n
=
fib_trie_get_next
(
&
iter
))
{
if
(
IS_LEAF
(
n
))
{
s
->
leaves
++
;
s
->
totdepth
+=
iter
.
depth
;
if
(
iter
.
depth
>
s
->
maxdepth
)
s
->
maxdepth
=
iter
.
depth
;
}
else
{
/*
* New tnode. Decend one level
*/
const
struct
tnode
*
tn
=
(
const
struct
tnode
*
)
n
;
int
i
;
s
->
tnodes
++
;
s
->
nodesizes
[
tn
->
bits
]
++
;
depth
++
;
n
=
ch
;
tn
=
(
struct
tnode
*
)
n
;
pend
=
tn
->
pos
+
tn
->
bits
;
cindex
=
0
;
}
}
else
{
cindex
++
;
for
(
i
=
0
;
i
<
(
1
<<
tn
->
bits
);
i
++
)
if
(
!
tn
->
child
[
i
])
s
->
nullpointers
++
;
}
/*
* Test if we are done
*/
while
(
cindex
>=
(
1
<<
tn
->
bits
))
{
/*
* Move upwards and test for root
* pop off all traversed nodes
*/
if
(
NODE_PARENT
(
tn
)
==
NULL
)
{
tn
=
NULL
;
n
=
NULL
;
break
;
}
cindex
=
tkey_extract_bits
(
tn
->
key
,
NODE_PARENT
(
tn
)
->
pos
,
NODE_PARENT
(
tn
)
->
bits
);
tn
=
NODE_PARENT
(
tn
);
cindex
++
;
n
=
(
struct
node
*
)
tn
;
pend
=
tn
->
pos
+
tn
->
bits
;
depth
--
;
}
}
}
rcu_read_unlock
();
return
s
;
}
#ifdef CONFIG_PROC_FS
static
struct
fib_alias
*
fib_triestat_get_first
(
struct
seq_file
*
seq
)
{
return
NULL
;
}
static
struct
fib_alias
*
fib_triestat_get_next
(
struct
seq_file
*
seq
)
{
return
NULL
;
}
static
void
*
fib_triestat_seq_start
(
struct
seq_file
*
seq
,
loff_t
*
pos
)
{
if
(
!
ip_fib_main_table
)
return
NULL
;
if
(
*
pos
)
return
fib_triestat_get_next
(
seq
);
else
return
SEQ_START_TOKEN
;
}
static
void
*
fib_triestat_seq_next
(
struct
seq_file
*
seq
,
void
*
v
,
loff_t
*
pos
)
{
++*
pos
;
if
(
v
==
SEQ_START_TOKEN
)
return
fib_triestat_get_first
(
seq
);
else
return
fib_triestat_get_next
(
seq
);
}
static
void
fib_triestat_seq_stop
(
struct
seq_file
*
seq
,
void
*
v
)
{
}
/*
* This outputs /proc/net/fib_triestats
*
* It always works in backward compatibility mode.
* The format of the file is not supposed to be changed.
*/
static
void
collect_and_show
(
struct
trie
*
t
,
struct
seq_file
*
seq
)
static
void
trie_show_stats
(
struct
seq_file
*
seq
,
struct
trie_stat
*
stat
)
{
int
bytes
=
0
;
/* How many bytes are used, a ref is 4 bytes */
int
i
,
max
,
pointers
;
struct
trie_stat
*
stat
;
int
avdepth
;
stat
=
trie_collect_stats
(
t
);
bytes
=
0
;
seq_printf
(
seq
,
"trie=%p
\n
"
,
t
);
unsigned
i
,
max
,
pointers
,
bytes
,
avdepth
;
if
(
stat
)
{
if
(
stat
->
leaves
)
avdepth
=
stat
->
totdepth
*
100
/
stat
->
leaves
;
else
avdepth
=
0
;
seq_printf
(
seq
,
"Aver depth: %d.%02d
\n
"
,
avdepth
/
100
,
avdepth
%
100
);
seq_printf
(
seq
,
"Max depth: %4d
\n
"
,
stat
->
maxdepth
);
seq_printf
(
seq
,
"Leaves: %d
\n
"
,
stat
->
leaves
);
bytes
+=
sizeof
(
struct
leaf
)
*
stat
->
leaves
;
seq_printf
(
seq
,
"Internal nodes: %d
\n
"
,
stat
->
tnodes
);
seq_printf
(
seq
,
"
\t
Aver depth: %d.%02d
\n
"
,
avdepth
/
100
,
avdepth
%
100
);
seq_printf
(
seq
,
"
\t
Max depth: %u
\n
"
,
stat
->
maxdepth
);
seq_printf
(
seq
,
"
\t
Leaves: %u
\n
"
,
stat
->
leaves
);
bytes
=
sizeof
(
struct
leaf
)
*
stat
->
leaves
;
seq_printf
(
seq
,
"
\t
Internal nodes: %d
\n\t
"
,
stat
->
tnodes
);
bytes
+=
sizeof
(
struct
tnode
)
*
stat
->
tnodes
;
max
=
MAX_CHILDS
-
1
;
while
(
max
>=
0
&&
stat
->
nodesizes
[
max
]
==
0
)
max
--
;
pointers
=
0
;
pointers
=
0
;
for
(
i
=
1
;
i
<=
max
;
i
++
)
if
(
stat
->
nodesizes
[
i
]
!=
0
)
{
seq_printf
(
seq
,
" %d: %d"
,
i
,
stat
->
nodesizes
[
i
]);
pointers
+=
(
1
<<
i
)
*
stat
->
nodesizes
[
i
];
}
seq_printf
(
seq
,
"
\n
"
);
seq_printf
(
seq
,
"Pointers: %d
\n
"
,
pointers
);
seq_putc
(
seq
,
'\n'
);
seq_printf
(
seq
,
"
\t
Pointers: %d
\n
"
,
pointers
);
bytes
+=
sizeof
(
struct
node
*
)
*
pointers
;
seq_printf
(
seq
,
"Null ptrs: %d
\n
"
,
stat
->
nullpointers
);
seq_printf
(
seq
,
"Total size: %d kB
\n
"
,
bytes
/
1024
);
kfree
(
stat
);
}
seq_printf
(
seq
,
"Total size: %d kB
\n
"
,
(
bytes
+
1023
)
/
1024
);
#ifdef CONFIG_IP_FIB_TRIE_STATS
seq_printf
(
seq
,
"Counters:
\n
---------
\n
"
);
...
...
@@ -2360,169 +2118,377 @@ static void collect_and_show(struct trie *t, struct seq_file *seq)
static
int
fib_triestat_seq_show
(
struct
seq_file
*
seq
,
void
*
v
)
{
char
bf
[
128
];
struct
trie_stat
*
stat
;
stat
=
kmalloc
(
sizeof
(
*
stat
),
GFP_KERNEL
);
if
(
!
stat
)
return
-
ENOMEM
;
if
(
v
==
SEQ_START_TOKEN
)
{
seq_printf
(
seq
,
"Basic info: size of leaf: %Zd bytes, size of tnode: %Zd bytes.
\n
"
,
sizeof
(
struct
leaf
),
sizeof
(
struct
tnode
));
if
(
trie_local
)
collect_and_show
(
trie_local
,
seq
);
if
(
trie_main
)
collect_and_show
(
trie_main
,
seq
);
}
else
{
snprintf
(
bf
,
sizeof
(
bf
),
"*
\t
%08X
\t
%08X"
,
200
,
400
);
if
(
trie_local
)
{
seq_printf
(
seq
,
"Local:
\n
"
);
trie_collect_stats
(
trie_local
,
stat
);
trie_show_stats
(
seq
,
stat
);
}
seq_printf
(
seq
,
"%-127s
\n
"
,
bf
);
if
(
trie_main
)
{
seq_printf
(
seq
,
"Main:
\n
"
);
trie_collect_stats
(
trie_main
,
stat
);
trie_show_stats
(
seq
,
stat
);
}
kfree
(
stat
);
return
0
;
}
static
struct
seq_operations
fib_triestat_seq_ops
=
{
.
start
=
fib_triestat_seq_start
,
.
next
=
fib_triestat_seq_next
,
.
stop
=
fib_triestat_seq_stop
,
.
show
=
fib_triestat_seq_show
,
};
static
int
fib_triestat_seq_open
(
struct
inode
*
inode
,
struct
file
*
file
)
{
struct
seq_file
*
seq
;
int
rc
=
-
ENOMEM
;
rc
=
seq_open
(
file
,
&
fib_triestat_seq_ops
);
if
(
rc
)
goto
out_kfree
;
seq
=
file
->
private_data
;
out:
return
rc
;
out_kfree:
goto
out
;
return
single_open
(
file
,
fib_triestat_seq_show
,
NULL
);
}
static
struct
file_operations
fib_triestat_
seq_
fops
=
{
static
struct
file_operations
fib_triestat_fops
=
{
.
owner
=
THIS_MODULE
,
.
open
=
fib_triestat_seq_open
,
.
read
=
seq_read
,
.
llseek
=
seq_lseek
,
.
release
=
s
eq_release_privat
e
,
.
release
=
s
ingle_releas
e
,
};
int
__init
fib_stat_proc_init
(
void
)
static
struct
node
*
fib_trie_get_idx
(
struct
fib_trie_iter
*
iter
,
loff_t
pos
)
{
if
(
!
proc_net_fops_create
(
"fib_triestat"
,
S_IRUGO
,
&
fib_triestat_seq_fops
))
return
-
ENOMEM
;
return
0
;
loff_t
idx
=
0
;
struct
node
*
n
;
for
(
n
=
fib_trie_get_first
(
iter
,
trie_local
);
n
;
++
idx
,
n
=
fib_trie_get_next
(
iter
))
{
if
(
pos
==
idx
)
return
n
;
}
for
(
n
=
fib_trie_get_first
(
iter
,
trie_main
);
n
;
++
idx
,
n
=
fib_trie_get_next
(
iter
))
{
if
(
pos
==
idx
)
return
n
;
}
return
NULL
;
}
void
__init
fib_stat_proc_exit
(
void
)
static
void
*
fib_trie_seq_start
(
struct
seq_file
*
seq
,
loff_t
*
pos
)
{
proc_net_remove
(
"fib_triestat"
);
rcu_read_lock
();
if
(
*
pos
==
0
)
return
SEQ_START_TOKEN
;
return
fib_trie_get_idx
(
seq
->
private
,
*
pos
-
1
);
}
static
struct
fib_alias
*
fib_trie_get_first
(
struct
seq_file
*
seq
)
static
void
*
fib_trie_seq_next
(
struct
seq_file
*
seq
,
void
*
v
,
loff_t
*
pos
)
{
struct
fib_trie_iter
*
iter
=
seq
->
private
;
void
*
l
=
v
;
++*
pos
;
if
(
v
==
SEQ_START_TOKEN
)
return
fib_trie_get_idx
(
iter
,
0
);
v
=
fib_trie_get_next
(
iter
);
BUG_ON
(
v
==
l
);
if
(
v
)
return
v
;
/* continue scan in next trie */
if
(
iter
->
trie
==
trie_local
)
return
fib_trie_get_first
(
iter
,
trie_main
);
return
NULL
;
}
static
struct
fib_alias
*
fib_trie_get_next
(
struct
seq_file
*
seq
)
static
void
fib_trie_seq_stop
(
struct
seq_file
*
seq
,
void
*
v
)
{
r
eturn
NULL
;
r
cu_read_unlock
()
;
}
static
void
*
fib_trie_seq_start
(
struct
seq_file
*
seq
,
loff_t
*
pos
)
static
void
seq_indent
(
struct
seq_file
*
seq
,
int
n
)
{
if
(
!
ip_fib_main_table
)
return
NULL
;
while
(
n
--
>
0
)
seq_puts
(
seq
,
" "
);
}
if
(
*
pos
)
return
fib_trie_get_next
(
seq
);
else
return
SEQ_START_TOKEN
;
static
inline
const
char
*
rtn_scope
(
enum
rt_scope_t
s
)
{
static
char
buf
[
32
];
switch
(
s
)
{
case
RT_SCOPE_UNIVERSE
:
return
"universe"
;
case
RT_SCOPE_SITE
:
return
"site"
;
case
RT_SCOPE_LINK
:
return
"link"
;
case
RT_SCOPE_HOST
:
return
"host"
;
case
RT_SCOPE_NOWHERE
:
return
"nowhere"
;
default:
snprintf
(
buf
,
sizeof
(
buf
),
"scope=%d"
,
s
);
return
buf
;
}
}
static
void
*
fib_trie_seq_next
(
struct
seq_file
*
seq
,
void
*
v
,
loff_t
*
pos
)
static
const
char
*
rtn_type_names
[
__RTN_MAX
]
=
{
[
RTN_UNSPEC
]
=
"UNSPEC"
,
[
RTN_UNICAST
]
=
"UNICAST"
,
[
RTN_LOCAL
]
=
"LOCAL"
,
[
RTN_BROADCAST
]
=
"BROADCAST"
,
[
RTN_ANYCAST
]
=
"ANYCAST"
,
[
RTN_MULTICAST
]
=
"MULTICAST"
,
[
RTN_BLACKHOLE
]
=
"BLACKHOLE"
,
[
RTN_UNREACHABLE
]
=
"UNREACHABLE"
,
[
RTN_PROHIBIT
]
=
"PROHIBIT"
,
[
RTN_THROW
]
=
"THROW"
,
[
RTN_NAT
]
=
"NAT"
,
[
RTN_XRESOLVE
]
=
"XRESOLVE"
,
};
static
inline
const
char
*
rtn_type
(
unsigned
t
)
{
++*
pos
;
static
char
buf
[
32
];
if
(
t
<
__RTN_MAX
&&
rtn_type_names
[
t
])
return
rtn_type_names
[
t
];
snprintf
(
buf
,
sizeof
(
buf
),
"type %d"
,
t
);
return
buf
;
}
/* Pretty print the trie */
static
int
fib_trie_seq_show
(
struct
seq_file
*
seq
,
void
*
v
)
{
const
struct
fib_trie_iter
*
iter
=
seq
->
private
;
struct
node
*
n
=
v
;
if
(
v
==
SEQ_START_TOKEN
)
return
fib_trie_get_first
(
seq
);
return
0
;
if
(
IS_TNODE
(
n
))
{
struct
tnode
*
tn
=
(
struct
tnode
*
)
n
;
t_key
prf
=
ntohl
(
MASK_PFX
(
tn
->
key
,
tn
->
pos
));
if
(
!
NODE_PARENT
(
n
))
{
if
(
iter
->
trie
==
trie_local
)
seq_puts
(
seq
,
"<local>:
\n
"
);
else
return
fib_trie_get_next
(
seq
);
seq_puts
(
seq
,
"<main>:
\n
"
);
}
else
{
seq_indent
(
seq
,
iter
->
depth
-
1
);
seq_printf
(
seq
,
" +-- %d.%d.%d.%d/%d
\n
"
,
NIPQUAD
(
prf
),
tn
->
pos
);
}
}
else
{
struct
leaf
*
l
=
(
struct
leaf
*
)
n
;
int
i
;
u32
val
=
ntohl
(
l
->
key
);
seq_indent
(
seq
,
iter
->
depth
);
seq_printf
(
seq
,
" |-- %d.%d.%d.%d
\n
"
,
NIPQUAD
(
val
));
for
(
i
=
32
;
i
>=
0
;
i
--
)
{
struct
leaf_info
*
li
=
find_leaf_info
(
&
l
->
list
,
i
);
if
(
li
)
{
struct
fib_alias
*
fa
;
list_for_each_entry_rcu
(
fa
,
&
li
->
falh
,
fa_list
)
{
seq_indent
(
seq
,
iter
->
depth
+
1
);
seq_printf
(
seq
,
" /%d %s %s"
,
i
,
rtn_scope
(
fa
->
fa_scope
),
rtn_type
(
fa
->
fa_type
));
if
(
fa
->
fa_tos
)
seq_printf
(
seq
,
"tos =%d
\n
"
,
fa
->
fa_tos
);
seq_putc
(
seq
,
'\n'
);
}
}
}
}
return
0
;
}
static
void
fib_trie_seq_stop
(
struct
seq_file
*
seq
,
void
*
v
)
static
struct
seq_operations
fib_trie_seq_ops
=
{
.
start
=
fib_trie_seq_start
,
.
next
=
fib_trie_seq_next
,
.
stop
=
fib_trie_seq_stop
,
.
show
=
fib_trie_seq_show
,
};
static
int
fib_trie_seq_open
(
struct
inode
*
inode
,
struct
file
*
file
)
{
struct
seq_file
*
seq
;
int
rc
=
-
ENOMEM
;
struct
fib_trie_iter
*
s
=
kmalloc
(
sizeof
(
*
s
),
GFP_KERNEL
);
if
(
!
s
)
goto
out
;
rc
=
seq_open
(
file
,
&
fib_trie_seq_ops
);
if
(
rc
)
goto
out_kfree
;
seq
=
file
->
private_data
;
seq
->
private
=
s
;
memset
(
s
,
0
,
sizeof
(
*
s
));
out:
return
rc
;
out_kfree:
kfree
(
s
);
goto
out
;
}
static
struct
file_operations
fib_trie_fops
=
{
.
owner
=
THIS_MODULE
,
.
open
=
fib_trie_seq_open
,
.
read
=
seq_read
,
.
llseek
=
seq_lseek
,
.
release
=
seq_release_private
,
};
static
unsigned
fib_flag_trans
(
int
type
,
u32
mask
,
const
struct
fib_info
*
fi
)
{
static
unsigned
type2flags
[
RTN_MAX
+
1
]
=
{
[
7
]
=
RTF_REJECT
,
[
8
]
=
RTF_REJECT
,
};
unsigned
flags
=
type2flags
[
type
];
if
(
fi
&&
fi
->
fib_nh
->
nh_gw
)
flags
|=
RTF_GATEWAY
;
if
(
mask
==
0xFFFFFFFF
)
flags
|=
RTF_HOST
;
flags
|=
RTF_UP
;
return
flags
;
}
/*
* This outputs /proc/net/
fib_tri
e.
*
*
It always works in backward compatibility mode.
*
The format of the file is not supposed to be changed.
* This outputs /proc/net/
rout
e.
*
The format of the file is not supposed to be changed
*
and needs to be same as fib_hash output to avoid breaking
*
legacy utilities
*/
static
int
fib_trie_seq_show
(
struct
seq_file
*
seq
,
void
*
v
)
static
int
fib_route_seq_show
(
struct
seq_file
*
seq
,
void
*
v
)
{
struct
leaf
*
l
=
v
;
int
i
;
char
bf
[
128
];
if
(
v
==
SEQ_START_TOKEN
)
{
if
(
trie_local
)
trie_dump_seq
(
seq
,
trie_local
);
seq_printf
(
seq
,
"%-127s
\n
"
,
"Iface
\t
Destination
\t
Gateway "
"
\t
Flags
\t
RefCnt
\t
Use
\t
Metric
\t
Mask
\t\t
MTU"
"
\t
Window
\t
IRTT"
);
return
0
;
}
if
(
trie_main
)
trie_dump_seq
(
seq
,
trie_main
);
}
else
{
if
(
IS_TNODE
(
l
))
return
0
;
for
(
i
=
32
;
i
>=
0
;
i
--
)
{
struct
leaf_info
*
li
=
find_leaf_info
(
&
l
->
list
,
i
);
struct
fib_alias
*
fa
;
u32
mask
,
prefix
;
if
(
!
li
)
continue
;
mask
=
inet_make_mask
(
li
->
plen
);
prefix
=
htonl
(
l
->
key
);
list_for_each_entry_rcu
(
fa
,
&
li
->
falh
,
fa_list
)
{
const
struct
fib_info
*
fi
=
rcu_dereference
(
fa
->
fa_info
);
unsigned
flags
=
fib_flag_trans
(
fa
->
fa_type
,
mask
,
fi
);
if
(
fa
->
fa_type
==
RTN_BROADCAST
||
fa
->
fa_type
==
RTN_MULTICAST
)
continue
;
if
(
fi
)
snprintf
(
bf
,
sizeof
(
bf
),
"*
\t
%08X
\t
%08X"
,
200
,
400
);
"%s
\t
%08X
\t
%08X
\t
%04X
\t
%d
\t
%u
\t
%d
\t
%08X
\t
%d
\t
%u
\t
%u"
,
fi
->
fib_dev
?
fi
->
fib_dev
->
name
:
"*"
,
prefix
,
fi
->
fib_nh
->
nh_gw
,
flags
,
0
,
0
,
fi
->
fib_priority
,
mask
,
(
fi
->
fib_advmss
?
fi
->
fib_advmss
+
40
:
0
),
fi
->
fib_window
,
fi
->
fib_rtt
>>
3
);
else
snprintf
(
bf
,
sizeof
(
bf
),
"*
\t
%08X
\t
%08X
\t
%04X
\t
%d
\t
%u
\t
%d
\t
%08X
\t
%d
\t
%u
\t
%u"
,
prefix
,
0
,
flags
,
0
,
0
,
0
,
mask
,
0
,
0
,
0
);
seq_printf
(
seq
,
"%-127s
\n
"
,
bf
);
}
}
return
0
;
}
static
struct
seq_operations
fib_
tri
e_seq_ops
=
{
static
struct
seq_operations
fib_
rout
e_seq_ops
=
{
.
start
=
fib_trie_seq_start
,
.
next
=
fib_trie_seq_next
,
.
stop
=
fib_trie_seq_stop
,
.
show
=
fib_tri
e_seq_show
,
.
show
=
fib_rout
e_seq_show
,
};
static
int
fib_
tri
e_seq_open
(
struct
inode
*
inode
,
struct
file
*
file
)
static
int
fib_
rout
e_seq_open
(
struct
inode
*
inode
,
struct
file
*
file
)
{
struct
seq_file
*
seq
;
int
rc
=
-
ENOMEM
;
struct
fib_trie_iter
*
s
=
kmalloc
(
sizeof
(
*
s
),
GFP_KERNEL
);
rc
=
seq_open
(
file
,
&
fib_trie_seq_ops
);
if
(
!
s
)
goto
out
;
rc
=
seq_open
(
file
,
&
fib_route_seq_ops
);
if
(
rc
)
goto
out_kfree
;
seq
=
file
->
private_data
;
seq
->
private
=
s
;
memset
(
s
,
0
,
sizeof
(
*
s
));
out:
return
rc
;
out_kfree:
kfree
(
s
);
goto
out
;
}
static
struct
file_operations
fib_
trie_seq
_fops
=
{
static
struct
file_operations
fib_
route
_fops
=
{
.
owner
=
THIS_MODULE
,
.
open
=
fib_tri
e_seq_open
,
.
open
=
fib_rout
e_seq_open
,
.
read
=
seq_read
,
.
llseek
=
seq_lseek
,
.
release
=
seq_release_private
,
.
release
=
seq_release_private
,
};
int
__init
fib_proc_init
(
void
)
{
if
(
!
proc_net_fops_create
(
"fib_trie"
,
S_IRUGO
,
&
fib_trie_seq_fops
))
return
-
ENOMEM
;
if
(
!
proc_net_fops_create
(
"fib_trie"
,
S_IRUGO
,
&
fib_trie_fops
))
goto
out1
;
if
(
!
proc_net_fops_create
(
"fib_triestat"
,
S_IRUGO
,
&
fib_triestat_fops
))
goto
out2
;
if
(
!
proc_net_fops_create
(
"route"
,
S_IRUGO
,
&
fib_route_fops
))
goto
out3
;
return
0
;
out3:
proc_net_remove
(
"fib_triestat"
);
out2:
proc_net_remove
(
"fib_trie"
);
out1:
return
-
ENOMEM
;
}
void
__init
fib_proc_exit
(
void
)
{
proc_net_remove
(
"fib_trie"
);
proc_net_remove
(
"fib_triestat"
);
proc_net_remove
(
"route"
);
}
#endif
/* CONFIG_PROC_FS */
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