aboutsummaryrefslogtreecommitdiff
path: root/net/sctp/probe.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/sctp/probe.c')
-rw-r--r--net/sctp/probe.c72
1 files changed, 49 insertions, 23 deletions
diff --git a/net/sctp/probe.c b/net/sctp/probe.c
index bc6cd75cc1d..5e68b94ee64 100644
--- a/net/sctp/probe.c
+++ b/net/sctp/probe.c
@@ -38,6 +38,7 @@
#include <net/sctp/sctp.h>
#include <net/sctp/sm.h>
+MODULE_SOFTDEP("pre: sctp");
MODULE_AUTHOR("Wei Yongjun <yjwei@cn.fujitsu.com>");
MODULE_DESCRIPTION("SCTP snooper");
MODULE_LICENSE("GPL");
@@ -46,6 +47,10 @@ static int port __read_mostly = 0;
MODULE_PARM_DESC(port, "Port to match (0=all)");
module_param(port, int, 0);
+static unsigned int fwmark __read_mostly = 0;
+MODULE_PARM_DESC(fwmark, "skb mark to match (0=no mark)");
+module_param(fwmark, uint, 0);
+
static int bufsize __read_mostly = 64 * 1024;
MODULE_PARM_DESC(bufsize, "Log buffer size (default 64k)");
module_param(bufsize, int, 0);
@@ -63,7 +68,7 @@ static struct {
struct timespec tstart;
} sctpw;
-static void printl(const char *fmt, ...)
+static __printf(1, 2) void printl(const char *fmt, ...)
{
va_list args;
int len;
@@ -122,21 +127,26 @@ static const struct file_operations sctpprobe_fops = {
.llseek = noop_llseek,
};
-sctp_disposition_t jsctp_sf_eat_sack(const struct sctp_endpoint *ep,
- const struct sctp_association *asoc,
- const sctp_subtype_t type,
- void *arg,
- sctp_cmd_seq_t *commands)
+static sctp_disposition_t jsctp_sf_eat_sack(struct net *net,
+ const struct sctp_endpoint *ep,
+ const struct sctp_association *asoc,
+ const sctp_subtype_t type,
+ void *arg,
+ sctp_cmd_seq_t *commands)
{
+ struct sctp_chunk *chunk = arg;
+ struct sk_buff *skb = chunk->skb;
struct sctp_transport *sp;
static __u32 lcwnd = 0;
struct timespec now;
sp = asoc->peer.primary_path;
- if ((full || sp->cwnd != lcwnd) &&
- (!port || asoc->peer.port == port ||
- ep->base.bind_addr.port == port)) {
+ if (((port == 0 && fwmark == 0) ||
+ asoc->peer.port == port ||
+ ep->base.bind_addr.port == port ||
+ (fwmark > 0 && skb->mark == fwmark)) &&
+ (full || sp->cwnd != lcwnd)) {
lcwnd = sp->cwnd;
getnstimeofday(&now);
@@ -154,13 +164,8 @@ sctp_disposition_t jsctp_sf_eat_sack(const struct sctp_endpoint *ep,
if (sp == asoc->peer.primary_path)
printl("*");
- if (sp->ipaddr.sa.sa_family == AF_INET)
- printl("%pI4 ", &sp->ipaddr.v4.sin_addr);
- else
- printl("%pI6 ", &sp->ipaddr.v6.sin6_addr);
-
- printl("%2u %8u %8u %8u %8u %8u ",
- sp->state, sp->cwnd, sp->ssthresh,
+ printl("%pISc %2u %8u %8u %8u %8u %8u ",
+ &sp->ipaddr, sp->state, sp->cwnd, sp->ssthresh,
sp->flight_size, sp->partial_bytes_acked,
sp->pathmtu);
}
@@ -178,29 +183,50 @@ static struct jprobe sctp_recv_probe = {
.entry = jsctp_sf_eat_sack,
};
+static __init int sctp_setup_jprobe(void)
+{
+ int ret = register_jprobe(&sctp_recv_probe);
+
+ if (ret) {
+ if (request_module("sctp"))
+ goto out;
+ ret = register_jprobe(&sctp_recv_probe);
+ }
+
+out:
+ return ret;
+}
+
static __init int sctpprobe_init(void)
{
int ret = -ENOMEM;
+ /* Warning: if the function signature of sctp_sf_eat_sack_6_2,
+ * has been changed, you also have to change the signature of
+ * jsctp_sf_eat_sack, otherwise you end up right here!
+ */
+ BUILD_BUG_ON(__same_type(sctp_sf_eat_sack_6_2,
+ jsctp_sf_eat_sack) == 0);
+
init_waitqueue_head(&sctpw.wait);
spin_lock_init(&sctpw.lock);
if (kfifo_alloc(&sctpw.fifo, bufsize, GFP_KERNEL))
return ret;
- if (!proc_net_fops_create(&init_net, procname, S_IRUSR,
- &sctpprobe_fops))
+ if (!proc_create(procname, S_IRUSR, init_net.proc_net,
+ &sctpprobe_fops))
goto free_kfifo;
- ret = register_jprobe(&sctp_recv_probe);
+ ret = sctp_setup_jprobe();
if (ret)
goto remove_proc;
- pr_info("probe registered (port=%d)\n", port);
-
+ pr_info("probe registered (port=%d/fwmark=%u) bufsize=%u\n",
+ port, fwmark, bufsize);
return 0;
remove_proc:
- proc_net_remove(&init_net, procname);
+ remove_proc_entry(procname, init_net.proc_net);
free_kfifo:
kfifo_free(&sctpw.fifo);
return ret;
@@ -209,7 +235,7 @@ free_kfifo:
static __exit void sctpprobe_exit(void)
{
kfifo_free(&sctpw.fifo);
- proc_net_remove(&init_net, procname);
+ remove_proc_entry(procname, init_net.proc_net);
unregister_jprobe(&sctp_recv_probe);
}