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
0d2cfd9d
Commit
0d2cfd9d
authored
Sep 15, 2003
by
Stephen Hemminger
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[IPVS]: Convert to seq_file.
parent
c31c7015
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
392 additions
and
242 deletions
+392
-242
net/ipv4/ipvs/ip_vs_app.c
net/ipv4/ipvs/ip_vs_app.c
+83
-33
net/ipv4/ipvs/ip_vs_conn.c
net/ipv4/ipvs/ip_vs_conn.c
+105
-53
net/ipv4/ipvs/ip_vs_ctl.c
net/ipv4/ipvs/ip_vs_ctl.c
+204
-156
No files found.
net/ipv4/ipvs/ip_vs_app.c
View file @
0d2cfd9d
...
...
@@ -35,6 +35,7 @@
#include <asm/system.h>
#include <linux/stat.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <net/ip_vs.h>
...
...
@@ -480,55 +481,104 @@ int ip_vs_app_pkt_in(struct ip_vs_conn *cp, struct sk_buff *skb)
}
#ifdef CONFIG_PROC_FS
/*
* /proc/net/ip_vs_app entry function
*/
static
int
ip_vs_app_getinfo
(
char
*
buffer
,
char
**
start
,
off_t
offset
,
int
length
)
#define SEQ_START_TOKEN ((void *)1)
static
struct
ip_vs_app
*
ip_vs_app_idx
(
loff_t
pos
)
{
off_t
pos
=
0
;
int
len
=
0
;
char
temp
[
64
];
struct
ip_vs_app
*
app
,
*
inc
;
loff_t
off
=
0
;
struct
list_head
*
e
,
*
i
;
pos
=
64
;
if
(
pos
>
offset
)
{
len
+=
sprintf
(
buffer
+
len
,
"%-63s
\n
"
,
"prot port usecnt name"
);
list_for_each
(
e
,
&
ip_vs_app_list
)
{
struct
ip_vs_app
*
app
=
list_entry
(
e
,
struct
ip_vs_app
,
a_list
);
list_for_each
(
i
,
&
app
->
incs_list
)
{
if
(
off
==
pos
)
return
list_entry
(
i
,
struct
ip_vs_app
,
a_list
);
++
off
;
}
}
return
NULL
;
}
static
void
*
ip_vs_app_seq_start
(
struct
seq_file
*
seq
,
loff_t
*
pos
)
{
down
(
&
__ip_vs_app_mutex
);
list_for_each
(
e
,
&
ip_vs_app_list
)
{
return
*
pos
?
ip_vs_app_idx
(
*
pos
-
1
)
:
SEQ_START_TOKEN
;
}
static
void
*
ip_vs_app_seq_next
(
struct
seq_file
*
seq
,
void
*
v
,
loff_t
*
pos
)
{
struct
ip_vs_app
*
inc
,
*
app
;
struct
list_head
*
i
,
*
e
;
++*
pos
;
if
(
v
==
SEQ_START_TOKEN
)
return
ip_vs_app_idx
(
0
);
inc
=
v
;
app
=
inc
->
app
;
if
((
i
=
inc
->
a_list
.
next
)
!=
&
app
->
incs_list
)
return
list_entry
(
i
,
struct
ip_vs_app
,
a_list
);
/* go on to next application */
for
(
e
=
app
->
a_list
.
next
;
e
!=
&
ip_vs_app_list
;
e
=
e
->
next
)
{
app
=
list_entry
(
e
,
struct
ip_vs_app
,
a_list
);
list_for_each
(
i
,
&
app
->
incs_list
)
{
inc
=
list_entry
(
i
,
struct
ip_vs_app
,
a_list
);
return
list_entry
(
i
,
struct
ip_vs_app
,
a_list
);
}
}
return
NULL
;
}
pos
+=
64
;
if
(
pos
<=
offset
)
continue
;
sprintf
(
temp
,
"%-3s %-7u %-6d %-17s"
,
static
void
ip_vs_app_seq_stop
(
struct
seq_file
*
seq
,
void
*
v
)
{
up
(
&
__ip_vs_app_mutex
);
}
static
int
ip_vs_app_seq_show
(
struct
seq_file
*
seq
,
void
*
v
)
{
if
(
v
==
SEQ_START_TOKEN
)
seq_puts
(
seq
,
"prot port usecnt name
\n
"
);
else
{
const
struct
ip_vs_app
*
inc
=
v
;
seq_printf
(
seq
,
"%-3s %-7u %-6d %-17s
\n
"
,
ip_vs_proto_name
(
inc
->
protocol
),
ntohs
(
inc
->
port
),
atomic_read
(
&
inc
->
usecnt
),
inc
->
name
);
len
+=
sprintf
(
buffer
+
len
,
"%-63s
\n
"
,
temp
);
if
(
pos
>=
offset
+
length
)
goto
done
;
}
}
done:
up
(
&
__ip_vs_app_mutex
);
return
0
;
}
*
start
=
buffer
+
len
-
(
pos
-
offset
);
/* Start of wanted data */
len
=
pos
-
offset
;
if
(
len
>
length
)
len
=
length
;
if
(
len
<
0
)
len
=
0
;
return
len
;
static
struct
seq_operations
ip_vs_app_seq_ops
=
{
.
start
=
ip_vs_app_seq_start
,
.
next
=
ip_vs_app_seq_next
,
.
stop
=
ip_vs_app_seq_stop
,
.
show
=
ip_vs_app_seq_show
,
};
static
int
ip_vs_app_open
(
struct
inode
*
inode
,
struct
file
*
file
)
{
return
seq_open
(
file
,
&
ip_vs_app_seq_ops
);
}
static
struct
file_operations
ip_vs_app_fops
=
{
.
owner
=
THIS_MODULE
,
.
open
=
ip_vs_app_open
,
.
read
=
seq_read
,
.
llseek
=
seq_lseek
,
.
release
=
seq_release
,
};
#endif
/*
* Replace a segment of data with a new segment
...
...
@@ -577,7 +627,7 @@ int ip_vs_skb_replace(struct sk_buff *skb, int pri,
int
ip_vs_app_init
(
void
)
{
/* we will replace it with proc_net_ipvs_create() soon */
proc_net_
create
(
"ip_vs_app"
,
0
,
ip_vs_app_getinfo
);
proc_net_
fops_create
(
"ip_vs_app"
,
0
,
&
ip_vs_app_fops
);
return
0
;
}
...
...
net/ipv4/ipvs/ip_vs_conn.c
View file @
0d2cfd9d
...
...
@@ -30,6 +30,7 @@
#include <linux/compiler.h>
#include <linux/vmalloc.h>
#include <linux/proc_fs.h>
/* for proc_net_* */
#include <linux/seq_file.h>
#include <linux/jhash.h>
#include <linux/random.h>
...
...
@@ -188,14 +189,13 @@ static inline struct ip_vs_conn *__ip_vs_conn_in_get
{
unsigned
hash
;
struct
ip_vs_conn
*
cp
;
struct
list_head
*
l
,
*
e
;
struct
list_head
*
e
;
hash
=
ip_vs_conn_hashkey
(
protocol
,
s_addr
,
s_port
);
l
=
&
ip_vs_conn_tab
[
hash
];
ct_read_lock
(
hash
);
for
(
e
=
l
->
next
;
e
!=
l
;
e
=
e
->
next
)
{
list_for_each
(
e
,
&
ip_vs_conn_tab
[
hash
]
)
{
cp
=
list_entry
(
e
,
struct
ip_vs_conn
,
c_list
);
if
(
s_addr
==
cp
->
caddr
&&
s_port
==
cp
->
cport
&&
d_port
==
cp
->
vport
&&
d_addr
==
cp
->
vaddr
&&
...
...
@@ -242,17 +242,16 @@ struct ip_vs_conn *ip_vs_conn_out_get
{
unsigned
hash
;
struct
ip_vs_conn
*
cp
,
*
ret
=
NULL
;
struct
list_head
*
l
,
*
e
;
struct
list_head
*
e
;
/*
* Check for "full" addressed entries
*/
hash
=
ip_vs_conn_hashkey
(
protocol
,
d_addr
,
d_port
);
l
=
&
ip_vs_conn_tab
[
hash
];
ct_read_lock
(
hash
);
for
(
e
=
l
->
next
;
e
!=
l
;
e
=
e
->
next
)
{
list_for_each
(
e
,
&
ip_vs_conn_tab
[
hash
]
)
{
cp
=
list_entry
(
e
,
struct
ip_vs_conn
,
c_list
);
if
(
d_addr
==
cp
->
caddr
&&
d_port
==
cp
->
cport
&&
s_port
==
cp
->
dport
&&
s_addr
==
cp
->
daddr
&&
...
...
@@ -615,61 +614,116 @@ ip_vs_conn_new(int proto, __u32 caddr, __u16 cport, __u32 vaddr, __u16 vport,
/*
* /proc/net/ip_vs_conn entries
*/
static
int
ip_vs_conn_getinfo
(
char
*
buffer
,
char
**
start
,
off_t
offset
,
int
length
)
#ifdef CONFIG_PROC_FS
#define SEQ_START_TOKEN ((void *)1)
static
void
*
ip_vs_conn_array
(
struct
seq_file
*
seq
,
loff_t
pos
)
{
off_t
pos
=
0
;
int
idx
,
len
=
0
;
char
temp
[
70
];
struct
ip_vs_conn
*
cp
;
struct
list_head
*
l
,
*
e
;
struct
list_head
*
e
;
int
idx
;
loff_t
off
=
0
;
pos
=
128
;
if
(
pos
>
offset
)
{
len
+=
sprintf
(
buffer
+
len
,
"%-127s
\n
"
,
"Pro FromIP FPrt ToIP TPrt DestIP DPrt State Expires"
);
for
(
idx
=
0
;
idx
<
IP_VS_CONN_TAB_SIZE
;
idx
++
)
{
ct_read_lock_bh
(
idx
);
list_for_each
(
e
,
&
ip_vs_conn_tab
[
idx
])
{
if
(
off
==
pos
)
{
seq
->
private
=
&
ip_vs_conn_tab
[
idx
];
return
list_entry
(
e
,
struct
ip_vs_conn
,
c_list
);
}
++
off
;
}
ct_read_unlock_bh
(
idx
);
}
for
(
idx
=
0
;
idx
<
IP_VS_CONN_TAB_SIZE
;
idx
++
)
{
/*
* Lock is actually only need in next loop
* we are called from uspace: must stop bh.
*/
return
NULL
;
}
static
void
*
ip_vs_conn_seq_start
(
struct
seq_file
*
seq
,
loff_t
*
pos
)
{
seq
->
private
=
NULL
;
return
*
pos
?
ip_vs_conn_array
(
seq
,
*
pos
-
1
)
:
SEQ_START_TOKEN
;
}
static
void
*
ip_vs_conn_seq_next
(
struct
seq_file
*
seq
,
void
*
v
,
loff_t
*
pos
)
{
struct
ip_vs_conn
*
cp
=
v
;
struct
list_head
*
e
,
*
l
=
seq
->
private
;
int
idx
;
++*
pos
;
if
(
v
==
SEQ_START_TOKEN
)
return
ip_vs_conn_array
(
seq
,
0
);
/* more on same hash chain? */
if
((
e
=
cp
->
c_list
.
next
)
!=
l
)
return
list_entry
(
e
,
struct
ip_vs_conn
,
c_list
);
idx
=
l
-
ip_vs_conn_tab
;
ct_read_unlock_bh
(
idx
);
while
(
++
idx
<
IP_VS_CONN_TAB_SIZE
)
{
ct_read_lock_bh
(
idx
);
list_for_each
(
e
,
&
ip_vs_conn_tab
[
idx
])
{
seq
->
private
=
&
ip_vs_conn_tab
[
idx
];
return
list_entry
(
e
,
struct
ip_vs_conn
,
c_list
);
}
ct_read_unlock_bh
(
idx
);
}
seq
->
private
=
NULL
;
return
NULL
;
}
l
=
&
ip_vs_conn_tab
[
idx
];
for
(
e
=
l
->
next
;
e
!=
l
;
e
=
e
->
next
)
{
cp
=
list_entry
(
e
,
struct
ip_vs_conn
,
c_list
);
pos
+=
128
;
if
(
pos
<=
offset
)
continue
;
sprintf
(
temp
,
"%-3s %08X %04X %08X %04X %08X %04X %-11s %7lu"
,
static
void
ip_vs_conn_seq_stop
(
struct
seq_file
*
seq
,
void
*
v
)
{
struct
list_head
*
l
=
seq
->
private
;
if
(
l
)
ct_read_unlock
(
l
-
ip_vs_conn_tab
);
}
static
int
ip_vs_conn_seq_show
(
struct
seq_file
*
seq
,
void
*
v
)
{
if
(
v
==
SEQ_START_TOKEN
)
seq_puts
(
seq
,
"Pro FromIP FPrt ToIP TPrt DestIP DPrt State Expires
\n
"
);
else
{
const
struct
ip_vs_conn
*
cp
=
v
;
seq_printf
(
seq
,
"%-3s %08X %04X %08X %04X %08X %04X %-11s %7lu
\n
"
,
ip_vs_proto_name
(
cp
->
protocol
),
ntohl
(
cp
->
caddr
),
ntohs
(
cp
->
cport
),
ntohl
(
cp
->
vaddr
),
ntohs
(
cp
->
vport
),
ntohl
(
cp
->
daddr
),
ntohs
(
cp
->
dport
),
ip_vs_state_name
(
cp
->
protocol
,
cp
->
state
),
(
cp
->
timer
.
expires
-
jiffies
)
/
HZ
);
len
+=
sprintf
(
buffer
+
len
,
"%-127s
\n
"
,
temp
);
if
(
pos
>=
offset
+
length
)
{
ct_read_unlock_bh
(
idx
);
goto
done
;
}
}
ct_read_unlock_bh
(
idx
);
}
return
0
;
}
done:
*
start
=
buffer
+
len
-
(
pos
-
offset
);
/* Start of wanted data */
len
=
pos
-
offset
;
if
(
len
>
length
)
len
=
length
;
if
(
len
<
0
)
len
=
0
;
return
len
;
static
struct
seq_operations
ip_vs_conn_seq_ops
=
{
.
start
=
ip_vs_conn_seq_start
,
.
next
=
ip_vs_conn_seq_next
,
.
stop
=
ip_vs_conn_seq_stop
,
.
show
=
ip_vs_conn_seq_show
,
};
static
int
ip_vs_conn_open
(
struct
inode
*
inode
,
struct
file
*
file
)
{
return
seq_open
(
file
,
&
ip_vs_conn_seq_ops
);
}
static
struct
file_operations
ip_vs_conn_fops
=
{
.
owner
=
THIS_MODULE
,
.
open
=
ip_vs_conn_open
,
.
read
=
seq_read
,
.
llseek
=
seq_lseek
,
.
release
=
seq_release
,
};
#endif
/*
* Randomly drop connection entries before running out of memory
...
...
@@ -707,7 +761,7 @@ void ip_vs_random_dropentry(void)
{
int
idx
;
struct
ip_vs_conn
*
cp
;
struct
list_head
*
l
,
*
e
;
struct
list_head
*
e
;
struct
ip_vs_conn
*
ct
;
/*
...
...
@@ -721,8 +775,7 @@ void ip_vs_random_dropentry(void)
*/
ct_write_lock
(
hash
);
l
=
&
ip_vs_conn_tab
[
hash
];
for
(
e
=
l
->
next
;
e
!=
l
;
e
=
e
->
next
)
{
list_for_each
(
e
,
&
ip_vs_conn_tab
[
hash
])
{
cp
=
list_entry
(
e
,
struct
ip_vs_conn
,
c_list
);
if
(
!
cp
->
cport
&&
!
(
cp
->
flags
&
IP_VS_CONN_F_NO_CPORT
))
/* connection template */
...
...
@@ -775,7 +828,7 @@ static void ip_vs_conn_flush(void)
{
int
idx
;
struct
ip_vs_conn
*
cp
;
struct
list_head
*
l
,
*
e
;
struct
list_head
*
e
;
struct
ip_vs_conn
*
ct
;
flush_again:
...
...
@@ -785,8 +838,7 @@ static void ip_vs_conn_flush(void)
*/
ct_write_lock_bh
(
idx
);
l
=
&
ip_vs_conn_tab
[
idx
];
for
(
e
=
l
->
next
;
e
!=
l
;
e
=
e
->
next
)
{
list_for_each
(
e
,
&
ip_vs_conn_tab
[
idx
])
{
cp
=
list_entry
(
e
,
struct
ip_vs_conn
,
c_list
);
atomic_inc
(
&
cp
->
refcnt
);
ct_write_unlock
(
idx
);
...
...
@@ -848,7 +900,7 @@ int ip_vs_conn_init(void)
__ip_vs_conntbl_lock_array
[
idx
].
l
=
RW_LOCK_UNLOCKED
;
}
proc_net_
create
(
"ip_vs_conn"
,
0
,
ip_vs_conn_getinfo
);
proc_net_
fops_create
(
"ip_vs_conn"
,
0
,
&
ip_vs_conn_fops
);
/* calculate the random value for connection hash */
get_random_bytes
(
&
ip_vs_conn_rnd
,
sizeof
(
ip_vs_conn_rnd
));
...
...
net/ipv4/ipvs/ip_vs_ctl.c
View file @
0d2cfd9d
...
...
@@ -31,6 +31,8 @@
#include <linux/proc_fs.h>
#include <linux/timer.h>
#include <linux/swap.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
...
...
@@ -1507,207 +1509,253 @@ static struct ip_vs_sysctl_table ipv4_vs_table = {
{
0
}}
};
#ifdef CONFIG_PROC_FS
struct
ip_vs_iter
{
struct
list_head
*
table
;
int
bucket
;
};
#define SEQ_START_TOKEN ((void *)1)
/*
* Write the contents of the VS rule table to a PROCfs file.
* (It is kept just for backward compatibility)
*/
static
inline
char
*
ip_vs_fwd_name
(
unsigned
flags
)
static
inline
c
onst
c
har
*
ip_vs_fwd_name
(
unsigned
flags
)
{
char
*
fwd
;
switch
(
flags
&
IP_VS_CONN_F_FWD_MASK
)
{
case
IP_VS_CONN_F_LOCALNODE
:
fwd
=
"Local"
;
break
;
return
"Local"
;
case
IP_VS_CONN_F_TUNNEL
:
fwd
=
"Tunnel"
;
break
;
return
"Tunnel"
;
case
IP_VS_CONN_F_DROUTE
:
fwd
=
"Route"
;
break
;
return
"Route"
;
default:
fwd
=
"Masq"
;
return
"Masq"
;
}
return
fwd
;
}
static
inline
int
sprintf_dest
(
char
*
str
,
struct
ip_vs_dest
*
dest
)
{
return
sprintf
(
str
,
" -> %08X:%04X %-7s %-6d %-10d %-10d"
,
ntohl
(
dest
->
addr
),
ntohs
(
dest
->
port
),
ip_vs_fwd_name
(
atomic_read
(
&
dest
->
conn_flags
)),
atomic_read
(
&
dest
->
weight
),
atomic_read
(
&
dest
->
activeconns
),
atomic_read
(
&
dest
->
inactconns
));
}
static
int
ip_vs_get_info
(
char
*
buf
,
char
**
start
,
off_t
offset
,
int
length
)
/* Get the Nth entry in the two lists */
static
struct
ip_vs_service
*
ip_vs_info_array
(
struct
seq_file
*
seq
,
loff_t
pos
)
{
int
len
=
0
;
off_t
pos
=
0
;
char
temp
[
64
],
temp2
[
32
];
struct
ip_vs_iter
*
iter
=
seq
->
private
;
int
idx
;
struct
ip_vs_service
*
svc
;
struct
ip_vs_dest
*
dest
;
struct
list_head
*
l
,
*
e
,
*
p
,
*
q
;
struct
list_head
*
e
;
/*
* Note: since the length of the buffer is usually the multiple
* of 512, it is good to use fixed record of the divisor of 512,
* so that records won't be truncated at buffer boundary.
*/
pos
=
192
;
if
(
pos
>
offset
)
{
sprintf
(
temp
,
"IP Virtual Server version %d.%d.%d (size=%d)"
,
NVERSION
(
IP_VS_VERSION_CODE
),
IP_VS_CONN_TAB_SIZE
);
len
+=
sprintf
(
buf
+
len
,
"%-63s
\n
"
,
temp
);
len
+=
sprintf
(
buf
+
len
,
"%-63s
\n
"
,
"Prot LocalAddress:Port Scheduler Flags"
);
len
+=
sprintf
(
buf
+
len
,
"%-63s
\n
"
,
" -> RemoteAddress:Port Forward Weight ActiveConn InActConn"
);
/* look in hash by protocol */
for
(
idx
=
0
;
idx
<
IP_VS_SVC_TAB_SIZE
;
idx
++
)
{
list_for_each
(
e
,
&
ip_vs_svc_table
[
idx
])
{
if
(
pos
--
==
0
){
iter
->
table
=
ip_vs_svc_table
;
iter
->
bucket
=
idx
;
return
list_entry
(
e
,
struct
ip_vs_service
,
s_list
);
}
}
}
/* keep looking in fwmark */
for
(
idx
=
0
;
idx
<
IP_VS_SVC_TAB_SIZE
;
idx
++
)
{
list_for_each
(
e
,
&
ip_vs_svc_fwm_table
[
idx
])
{
if
(
pos
--
==
0
)
{
iter
->
table
=
ip_vs_svc_fwm_table
;
iter
->
bucket
=
idx
;
return
list_entry
(
e
,
struct
ip_vs_service
,
f_list
);
}
}
}
return
NULL
;
}
static
void
*
ip_vs_info_seq_start
(
struct
seq_file
*
seq
,
loff_t
*
pos
)
{
read_lock_bh
(
&
__ip_vs_svc_lock
);
return
*
pos
?
ip_vs_info_array
(
seq
,
*
pos
-
1
)
:
SEQ_START_TOKEN
;
}
/* print the service table hashed by <protocol,addr,port> */
for
(
idx
=
0
;
idx
<
IP_VS_SVC_TAB_SIZE
;
idx
++
)
{
l
=
&
ip_vs_svc_table
[
idx
];
for
(
e
=
l
->
next
;
e
!=
l
;
e
=
e
->
next
)
{
svc
=
list_entry
(
e
,
struct
ip_vs_service
,
s_list
);
pos
+=
64
;
if
(
pos
>
offset
)
{
if
(
svc
->
flags
&
IP_VS_SVC_F_PERSISTENT
)
sprintf
(
temp2
,
"persistent %d %08X"
,
svc
->
timeout
,
ntohl
(
svc
->
netmask
));
else
temp2
[
0
]
=
'\0'
;
sprintf
(
temp
,
"%s %08X:%04X %s %s"
,
ip_vs_proto_name
(
svc
->
protocol
),
ntohl
(
svc
->
addr
),
ntohs
(
svc
->
port
),
svc
->
scheduler
->
name
,
temp2
);
len
+=
sprintf
(
buf
+
len
,
"%-63s
\n
"
,
temp
);
if
(
len
>=
length
)
goto
done
;
}
static
void
*
ip_vs_info_seq_next
(
struct
seq_file
*
seq
,
void
*
v
,
loff_t
*
pos
)
{
struct
list_head
*
e
;
struct
ip_vs_iter
*
iter
;
struct
ip_vs_service
*
svc
;
++*
pos
;
if
(
v
==
SEQ_START_TOKEN
)
return
ip_vs_info_array
(
seq
,
0
);
svc
=
v
;
iter
=
seq
->
private
;
p
=
&
svc
->
destinations
;
for
(
q
=
p
->
next
;
q
!=
p
;
q
=
q
->
next
)
{
dest
=
list_entry
(
q
,
struct
ip_vs_dest
,
n_list
);
pos
+=
64
;
if
(
pos
<=
offset
)
continue
;
sprintf_dest
(
temp
,
dest
);
len
+=
sprintf
(
buf
+
len
,
"%-63s
\n
"
,
temp
);
if
(
len
>=
length
)
goto
done
;
if
(
iter
->
table
==
ip_vs_svc_table
)
{
/* next service in table hashed by protocol */
if
((
e
=
svc
->
s_list
.
next
)
!=
&
ip_vs_svc_table
[
iter
->
bucket
])
return
list_entry
(
e
,
struct
ip_vs_service
,
s_list
);
while
(
++
iter
->
bucket
<
IP_VS_SVC_TAB_SIZE
)
{
list_for_each
(
e
,
&
ip_vs_svc_table
[
iter
->
bucket
])
{
return
list_entry
(
e
,
struct
ip_vs_service
,
s_list
);
}
}
iter
->
table
=
ip_vs_svc_fwm_table
;
iter
->
bucket
=
-
1
;
goto
scan_fwmark
;
}
/* print the service table hashed by fwmark */
for
(
idx
=
0
;
idx
<
IP_VS_SVC_TAB_SIZE
;
idx
++
)
{
l
=
&
ip_vs_svc_fwm_table
[
idx
];
for
(
e
=
l
->
next
;
e
!=
l
;
e
=
e
->
next
)
{
svc
=
list_entry
(
e
,
struct
ip_vs_service
,
f_list
);
pos
+=
64
;
if
(
pos
>
offset
)
{
/* next service in hashed by fwmark */
if
((
e
=
svc
->
f_list
.
next
)
!=
&
ip_vs_svc_fwm_table
[
iter
->
bucket
])
return
list_entry
(
e
,
struct
ip_vs_service
,
f_list
);
scan_fwmark:
while
(
++
iter
->
bucket
<
IP_VS_SVC_TAB_SIZE
)
{
list_for_each
(
e
,
&
ip_vs_svc_fwm_table
[
iter
->
bucket
])
return
list_entry
(
e
,
struct
ip_vs_service
,
f_list
);
}
return
NULL
;
}
static
void
ip_vs_info_seq_stop
(
struct
seq_file
*
seq
,
void
*
v
)
{
read_unlock_bh
(
&
__ip_vs_svc_lock
);
}
static
int
ip_vs_info_seq_show
(
struct
seq_file
*
seq
,
void
*
v
)
{
if
(
v
==
SEQ_START_TOKEN
)
{
seq_printf
(
seq
,
"IP Virtual Server version %d.%d.%d (size=%d)
\n
"
,
NVERSION
(
IP_VS_VERSION_CODE
),
IP_VS_CONN_TAB_SIZE
);
seq_puts
(
seq
,
"Prot LocalAddress:Port Scheduler Flags
\n
"
);
seq_puts
(
seq
,
" -> RemoteAddress:Port Forward Weight ActiveConn InActConn
\n
"
);
}
else
{
const
struct
ip_vs_service
*
svc
=
v
;
const
struct
ip_vs_iter
*
iter
=
seq
->
private
;
const
struct
ip_vs_dest
*
dest
;
if
(
iter
->
table
==
ip_vs_svc_table
)
seq_printf
(
seq
,
"%s %08X:%04X %s "
,
ip_vs_proto_name
(
svc
->
protocol
),
ntohl
(
svc
->
addr
),
ntohs
(
svc
->
port
),
svc
->
scheduler
->
name
);
else
seq_printf
(
seq
,
"FWM %08X %s "
,
svc
->
fwmark
,
svc
->
scheduler
->
name
);
if
(
svc
->
flags
&
IP_VS_SVC_F_PERSISTENT
)
sprintf
(
temp2
,
"persistent %d %08X
"
,
seq_printf
(
seq
,
"persistent %d %08X
\n
"
,
svc
->
timeout
,
ntohl
(
svc
->
netmask
));
else
temp2
[
0
]
=
'\0'
;
seq_putc
(
seq
,
'\n'
)
;
sprintf
(
temp
,
"FWM %08X %s %s"
,
svc
->
fwmark
,
svc
->
scheduler
->
name
,
temp2
);
len
+=
sprintf
(
buf
+
len
,
"%-63s
\n
"
,
temp
);
if
(
len
>=
length
)
goto
done
;
}
p
=
&
svc
->
destinations
;
for
(
q
=
p
->
next
;
q
!=
p
;
q
=
q
->
next
)
{
dest
=
list_entry
(
q
,
struct
ip_vs_dest
,
n_list
);
pos
+=
64
;
if
(
pos
<=
offset
)
continue
;
sprintf_dest
(
temp
,
dest
);
len
+=
sprintf
(
buf
+
len
,
"%-63s
\n
"
,
temp
);
if
(
len
>=
length
)
goto
done
;
}
list_for_each_entry
(
dest
,
&
svc
->
destinations
,
n_list
)
{
seq_printf
(
seq
,
" -> %08X:%04X %-7s %-6d %-10d %-10d
\n
"
,
ntohl
(
dest
->
addr
),
ntohs
(
dest
->
port
),
ip_vs_fwd_name
(
atomic_read
(
&
dest
->
conn_flags
)),
atomic_read
(
&
dest
->
weight
),
atomic_read
(
&
dest
->
activeconns
),
atomic_read
(
&
dest
->
inactconns
));
}
}
return
0
;
}
done:
read_unlock_bh
(
&
__ip_vs_svc_lock
);
static
struct
seq_operations
ip_vs_info_seq_ops
=
{
.
start
=
ip_vs_info_seq_start
,
.
next
=
ip_vs_info_seq_next
,
.
stop
=
ip_vs_info_seq_stop
,
.
show
=
ip_vs_info_seq_show
,
};
static
int
ip_vs_info_open
(
struct
inode
*
inode
,
struct
file
*
file
)
{
struct
seq_file
*
seq
;
int
rc
=
-
ENOMEM
;
struct
ip_vs_iter
*
s
=
kmalloc
(
sizeof
(
*
s
),
GFP_KERNEL
);
if
(
!
s
)
goto
out
;
rc
=
seq_open
(
file
,
&
ip_vs_info_seq_ops
);
if
(
rc
)
goto
out_kfree
;
*
start
=
buf
+
len
-
(
pos
-
offset
);
/* Start of wanted data */
len
=
pos
-
offset
;
if
(
len
>
length
)
len
=
length
;
if
(
len
<
0
)
len
=
0
;
return
len
;
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
ip_vs_info_fops
=
{
.
owner
=
THIS_MODULE
,
.
open
=
ip_vs_info_open
,
.
read
=
seq_read
,
.
llseek
=
seq_lseek
,
.
release
=
seq_release_private
,
};
#endif
struct
ip_vs_stats
ip_vs_stats
;
static
int
ip_vs_stats_get_info
(
char
*
buf
,
char
**
start
,
off_t
offset
,
int
length
)
#ifdef CONFIG_PROC_FS
static
int
ip_vs_stats_show
(
struct
seq_file
*
seq
,
void
*
v
)
{
int
len
=
0
;
off_t
pos
=
0
;
char
temp
[
64
];
pos
+=
320
;
if
(
pos
>
offset
)
{
len
+=
sprintf
(
buf
+
len
,
"%-63s
\n
%-63s
\n
"
,
/* 01234567 01234567 01234567 0123456701234567 0123456701234567 */
" Total Incoming Outgoing Incoming Outgoing"
,
" Conns Packets Packets Bytes Bytes"
);
seq_puts
(
seq
,
" Total Incoming Outgoing Incoming Outgoing
\n
"
);
seq_printf
(
seq
,
" Conns Packets Packets Bytes Bytes
\n
"
);
spin_lock_bh
(
&
ip_vs_stats
.
lock
);
sprintf
(
temp
,
"%8X %8X %8X %8X%08X %8X%08X"
,
ip_vs_stats
.
conns
,
ip_vs_stats
.
inpkts
,
ip_vs_stats
.
outpkts
,
(
__u32
)(
ip_vs_stats
.
inbytes
>>
32
),
(
__u32
)
ip_vs_stats
.
inbytes
,
(
__u32
)(
ip_vs_stats
.
outbytes
>>
32
),
(
__u32
)
ip_vs_stats
.
outbytes
);
len
+=
sprintf
(
buf
+
len
,
"%-62s
\n\n
"
,
temp
);
len
+=
sprintf
(
buf
+
len
,
"%-63s
\n
"
,
seq_printf
(
seq
,
"%8X %8X %8X %16LX %16LX
\n\n
"
,
ip_vs_stats
.
conns
,
ip_vs_stats
.
inpkts
,
ip_vs_stats
.
outpkts
,
ip_vs_stats
.
inbytes
,
ip_vs_stats
.
outbytes
);
/* 01234567 01234567 01234567 0123456701234567 0123456701234567 */
" Conns/s Pkts/s Pkts/s Bytes/s Bytes/s"
);
sprintf
(
temp
,
"%8X %8X %8X %16X %16X"
,
seq_puts
(
seq
,
" Conns/s Pkts/s Pkts/s Bytes/s Bytes/s
\n
"
);
seq_printf
(
seq
,
"%8X %8X %8X %16X %16X
\n
"
,
ip_vs_stats
.
cps
,
ip_vs_stats
.
inpps
,
ip_vs_stats
.
outpps
,
ip_vs_stats
.
inbps
,
ip_vs_stats
.
outbps
);
len
+=
sprintf
(
buf
+
len
,
"%-63s
\n
"
,
temp
);
spin_unlock_bh
(
&
ip_vs_stats
.
lock
);
}
*
start
=
buf
+
len
-
(
pos
-
offset
);
/* Start of wanted data */
len
=
pos
-
offset
;
if
(
len
>
length
)
len
=
length
;
if
(
len
<
0
)
len
=
0
;
return
len
;
return
0
;
}
static
int
ip_vs_stats_seq_open
(
struct
inode
*
inode
,
struct
file
*
file
)
{
return
single_open
(
file
,
ip_vs_stats_show
,
NULL
);
}
static
struct
file_operations
ip_vs_stats_fops
=
{
.
owner
=
THIS_MODULE
,
.
open
=
ip_vs_stats_seq_open
,
.
read
=
seq_read
,
.
llseek
=
seq_lseek
,
.
release
=
single_release
,
};
#endif
/*
* Set timeout values for tcp tcpfin udp in the timeout_table.
...
...
@@ -2195,8 +2243,8 @@ int ip_vs_control_init(void)
return
ret
;
}
proc_net_
create
(
"ip_vs"
,
0
,
ip_vs_get_info
);
proc_net_
create
(
"ip_vs_stats"
,
0
,
ip_vs_stats_get_info
);
proc_net_
fops_create
(
"ip_vs"
,
0
,
&
ip_vs_info_fops
);
proc_net_
fops_create
(
"ip_vs_stats"
,
0
,
&
ip_vs_stats_fops
);
ipv4_vs_table
.
sysctl_header
=
register_sysctl_table
(
ipv4_vs_table
.
root_dir
,
0
);
...
...
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