On Tue, 2016-03-01 at 11:11 +0000, Brian Russell wrote: > Module can register for Type 1 or specified classes of Type 2 metadata > and will then log incoming matching packets.
This logging mechanism seems like a way to fill/DoS logs. Maybe use pr_info_ratelimit? Maybe use the trace_events mechanisms instead? > Signed-off-by: Brian Russell <bruss...@brocade.com> > --- > net/ipv4/Kconfig | 8 ++++ > net/ipv4/Makefile | 1 + > net/ipv4/nsh_log.c | 135 > +++++++++++++++++++++++++++++++++++++++++++++++++++++ > 3 files changed, 144 insertions(+) > create mode 100644 net/ipv4/nsh_log.c > > diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig > index df14c59..87b6dde 100644 > --- a/net/ipv4/Kconfig > +++ b/net/ipv4/Kconfig > @@ -223,6 +223,14 @@ config NET_NSH > > To compile it as a module, choose M here. If unsure, say N. > > +config NET_NSH_LOG > + tristate 'NSH Metadata Logger' > + depends on NET_NSH > + help > + Log packets with incoming NSH metadata. > + > + To compile it as a module, choose M here. If unsure, say N. > + > config IP_MROUTE > bool "IP: multicast routing" > depends on IP_MULTICAST > diff --git a/net/ipv4/Makefile b/net/ipv4/Makefile > index 14b7995..69377fb 100644 > --- a/net/ipv4/Makefile > +++ b/net/ipv4/Makefile > @@ -25,6 +25,7 @@ obj-$(CONFIG_NET_FOU) += fou.o > obj-$(CONFIG_NET_IPGRE_DEMUX) += gre.o > obj-$(CONFIG_NET_IPGRE) += ip_gre.o > obj-$(CONFIG_NET_NSH) += nsh.o > +obj-$(CONFIG_NET_NSH_LOG) += nsh_log.o > obj-$(CONFIG_NET_UDP_TUNNEL) += udp_tunnel.o > obj-$(CONFIG_NET_IPVTI) += ip_vti.o > obj-$(CONFIG_SYN_COOKIES) += syncookies.o > diff --git a/net/ipv4/nsh_log.c b/net/ipv4/nsh_log.c > new file mode 100644 > index 0000000..3d774ed > --- /dev/null > +++ b/net/ipv4/nsh_log.c > @@ -0,0 +1,135 @@ > +/* > + * Network Service Header (NSH) logging module. > + * > + * Copyright (c) 2016 by Brocade Communications Systems, Inc. > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License version 2 as > + * published by the Free Software Foundation. > + */ > +#include > +#include > +#include > + > +static bool t1_enabled = false; > +module_param(t1_enabled, bool, 0444); > +MODULE_PARM_DESC(t1_enabled, "Type 1 Metadata log enabled"); > + > +#define MAX_T2_CLASSES 10 > +static unsigned int t2_classes[MAX_T2_CLASSES]; > +static int num_t2 = 0; > +module_param_array(t2_classes, uint, &num_t2, 0444); > +MODULE_PARM_DESC(t2_classes, "Type 2 Metadata classes log enabled"); > + > +static const char *nsh_next_proto(u8 next_proto) > +{ > + switch (next_proto) { > + case NSH_NEXT_PROTO_IPv4: > + return "IPv4"; > + case NSH_NEXT_PROTO_IPv6: > + return "IPv6"; > + case NSH_NEXT_PROTO_ETH: > + return "Eth"; > + default: > + return "Unknown"; > + } > +} > + > +/* Type 1 metadata has fixed length, 4 x 32-bit words */ > +static int nsh_log_t1(struct sk_buff *skb, u32 service_path_id, > + u8 service_index, u8 next_proto, > + struct nsh_metadata *ctx_hdr, unsigned int num_ctx_hdrs) > +{ > + u32 *data; > + > + if ((ctx_hdr->class != NSH_MD_CLASS_TYPE_1) || > + (ctx_hdr->type != NSH_MD_TYPE_TYPE_1) || > + (ctx_hdr->len != NSH_MD_LEN_TYPE_1) || > + (num_ctx_hdrs != 1)) > + return -EINVAL; > + > + data = ctx_hdr->data; > + pr_info("NSH T1 Rx(%s): SPI=%u SI=%u Next=%s" > + " MD 0x%08x 0x%08x 0x%08x 0x%08x\n", skb->dev->name, > + service_path_id, service_index, nsh_next_proto(next_proto), > + data[0], data[1], data[2], data[3]); > + > + return 0; > +} > + > +/* Type 2 metadata consists of a variable number of TLVs */ > +#define T2_BUFSIZE 512 > +static int nsh_log_t2(struct sk_buff *skb, u32 service_path_id, > + u8 service_index, u8 next_proto, > + struct nsh_metadata *ctx_hdrs, unsigned int num_ctx_hdrs) > +{ > + char t2_buf[T2_BUFSIZE]; > + int wrlen; > + u32 *data; > + int i,j; > + > + wrlen = snprintf(t2_buf, T2_BUFSIZE, > + "NSH T2 Class %u Rx(%s): SPI=%u SI=%u Next=%s MD", > + ctx_hdrs[0].class, skb->dev->name, service_path_id, > + service_index, nsh_next_proto(next_proto)); > + > + for (i = 0; i < num_ctx_hdrs; i++) { > + wrlen += snprintf(t2_buf+wrlen, T2_BUFSIZE-wrlen, > + " TLV%d Type=%u Len=%u", i+1, > + ctx_hdrs[i].type, ctx_hdrs[i].len); > + data = ctx_hdrs[i].data; > + for (j = 0; j < ctx_hdrs[i].len; j++) > + wrlen += snprintf(t2_buf+wrlen, T2_BUFSIZE-wrlen, > + " 0x%08x", data[j]); > + } > + pr_info("%s\n", t2_buf); > + return 0; > +} > + > +static struct nsh_listener nsh_log_t1_entry = { > + .class = NSH_MD_CLASS_TYPE_1, > + .notify = nsh_log_t1, > +}; > + > +static struct nsh_listener nsh_log_t2_entry[MAX_T2_CLASSES]; > + > +static int __init nsh_log_init(void) > +{ > + int i, err; > + > + if (t1_enabled) { > + err = nsh_register_listener(&nsh_log_t1_entry); > + > + if (err) > + return err; > + } > + > + for (i = 0; i < num_t2; i++) { > + nsh_log_t2_entry[i].class = t2_classes[i]; > + nsh_log_t2_entry[i].notify = nsh_log_t2; > + > + err = nsh_register_listener(&nsh_log_t2_entry[i]); > + > + if (err) > + return err; > + } > + return 0; > +} > + > +static void __exit nsh_log_exit(void) > +{ > + int i; > + > + if (t1_enabled) > + nsh_unregister_listener(&nsh_log_t1_entry); > + > + for (i = 0; i < num_t2; i++) > + nsh_unregister_listener(&nsh_log_t2_entry[i]); > +} > + > +module_init(nsh_log_init); > +module_exit(nsh_log_exit); > + > +MODULE_LICENSE("GPL"); > +MODULE_AUTHOR("Brian Russell <bruss...@brocade.com>"); > +MODULE_DESCRIPTION("NSH Metadata logger");