From dc5f7a04f2b446b5224be356c2fc79e88a5d3e8f Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Mon, 3 Jun 2013 22:49:19 +0200 Subject: irq: break out from xutils and save + restore Break out IRQ functionality from xutils, simplify it, and save + restore IRQ affinity list. Signed-off-by: Daniel Borkmann --- irq.c | 129 +++++++++++++++++++++++++++++++++++++++++++++++++++ irq.h | 10 ++++ netsniff-ng.c | 3 +- netsniff-ng/Makefile | 1 + trafgen.c | 2 + trafgen/Makefile | 1 + xutils.c | 108 ------------------------------------------ xutils.h | 3 -- 8 files changed, 145 insertions(+), 112 deletions(-) create mode 100644 irq.c create mode 100644 irq.h diff --git a/irq.c b/irq.c new file mode 100644 index 0000000..fbd1cbc --- /dev/null +++ b/irq.c @@ -0,0 +1,129 @@ +/* + * netsniff-ng - the packet sniffing beast + * Copyright 2009 - 2013 Daniel Borkmann. + * Copyright 2009, 2010 Emmanuel Roullit. + * Subject to the GPL, version 2. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "irq.h" +#include "die.h" +#include "xutils.h" + +int device_irq_number(const char *ifname) +{ + int irq = 0; + char buff[128], sysname[128]; + FILE *fp; + + if (!strncmp("lo", ifname, strlen("lo"))) + return 0; + + slprintf(sysname, sizeof(sysname), + "/sys/class/net/%s/device/irq", + ifname); + + fp = fopen(sysname, "r"); + if (!fp) + return -ENOENT; + + memset(buff, 0, sizeof(buff)); + + if (fgets(buff, sizeof(buff), fp) != NULL) { + buff[sizeof(buff) - 1] = 0; + irq = atoi(buff); + } + + fclose(fp); + return irq; +} + +static char nic_irq_affinity_list[128]; +static bool nic_irq_stored = false; +static int nic_irq = -1; + +static void device_save_irq_affinity_list(void) +{ + int ret, fd; + char file[128]; + + bug_on(nic_irq_stored); + + slprintf(file, sizeof(file), + "/proc/irq/%d/smp_affinity_list", nic_irq); + + fd = open(file, O_RDONLY); + if (fd < 0) + return; + + memset(nic_irq_affinity_list, 0, sizeof(nic_irq_affinity_list)); + + ret = read(fd, nic_irq_affinity_list, + sizeof(nic_irq_affinity_list)); + if (ret < 0) + panic("Cannot store NIC IRQ affinity!\n"); + + close(fd); + + nic_irq_stored = true; +} + +void device_restore_irq_affinity_list(void) +{ + int ret, fd; + char file[128]; + + if (!nic_irq_stored) + return; + + bug_on(nic_irq == -1); + + slprintf(file, sizeof(file), + "/proc/irq/%d/smp_affinity_list", nic_irq); + + fd = open(file, O_WRONLY); + if (fd < 0) + return; + + ret = write(fd, nic_irq_affinity_list, + sizeof(nic_irq_affinity_list)); + if (ret < 0) + panic("Cannot restore NIC IRQ affinity!\n"); + + close(fd); +} + +int device_set_irq_affinity_list(int irq, unsigned long from, unsigned long to) +{ + int ret, fd; + char file[128], list[64]; + + if (!nic_irq_stored) { + nic_irq = irq; + device_save_irq_affinity_list(); + } + + slprintf(file, sizeof(file), "/proc/irq/%d/smp_affinity_list", irq); + slprintf(list, sizeof(list), "%lu-%lu\n", from, to); + + fd = open(file, O_WRONLY); + if (fd < 0) + return -ENOENT; + + ret = write(fd, list, strlen(list)); + + close(fd); + return ret; +} + +int device_bind_irq_to_cpu(int irq, int cpu) +{ + return device_set_irq_affinity_list(irq, cpu, cpu); +} diff --git a/irq.h b/irq.h new file mode 100644 index 0000000..6c1c850 --- /dev/null +++ b/irq.h @@ -0,0 +1,10 @@ +#ifndef IRQ_H +#define IRQ_H + +extern int device_irq_number(const char *ifname); +extern int device_bind_irq_to_cpu(int irq, int cpu); +extern void device_restore_irq_affinity_list(void); +extern int device_set_irq_affinity_list(int irq, unsigned long from, + unsigned long to); + +#endif /* IRQ_H */ diff --git a/netsniff-ng.c b/netsniff-ng.c index 4d9abc8..899a148 100644 --- a/netsniff-ng.c +++ b/netsniff-ng.c @@ -32,6 +32,7 @@ #include "bpf.h" #include "xio.h" #include "die.h" +#include "irq.h" #include "geoip.h" #include "tprintf.h" #include "dissector.h" @@ -1398,7 +1399,7 @@ int main(int argc, char **argv) if (setsockmem) reset_system_socket_memory(vals, array_size(vals)); destroy_geoip(); - + device_restore_irq_affinity_list(); tprintf_cleanup(); free(ctx.device_in); diff --git a/netsniff-ng/Makefile b/netsniff-ng/Makefile index 211c726..7d5f89c 100644 --- a/netsniff-ng/Makefile +++ b/netsniff-ng/Makefile @@ -32,6 +32,7 @@ netsniff-ng-objs = dissector.o \ proto_vlan_q_in_q.o \ proto_mpls_unicast.o \ proto_80211_mac_hdr.o \ + irq.o \ xio.o \ xutils.o \ xmalloc.o \ diff --git a/trafgen.c b/trafgen.c index bbce64c..d493614 100644 --- a/trafgen.c +++ b/trafgen.c @@ -37,6 +37,7 @@ #include "mac80211.h" #include "xutils.h" #include "xio.h" +#include "irq.h" #include "built_in.h" #include "trafgen_conf.h" #include "tprintf.h" @@ -1083,6 +1084,7 @@ int main(int argc, char **argv) thread_out: xunlockme(); destroy_shared_var(stats, ctx.cpus); + device_restore_irq_affinity_list(); free(ctx.device); free(ctx.device_trans); diff --git a/trafgen/Makefile b/trafgen/Makefile index 8257ad1..914b61c 100644 --- a/trafgen/Makefile +++ b/trafgen/Makefile @@ -5,6 +5,7 @@ trafgen-libs = $(shell pkg-config --libs libnl-3.0) \ trafgen-objs = xmalloc.o \ xio.o \ xutils.o \ + irq.o \ mac80211.o \ ring_tx.o \ ring.o \ diff --git a/xutils.c b/xutils.c index 5421d7d..a5fbb3c 100644 --- a/xutils.c +++ b/xutils.c @@ -608,114 +608,6 @@ void device_set_flags(const char *ifname, const short flags) close(sock); } -int device_irq_number(const char *ifname) -{ - /* - * Since fetching IRQ numbers from SIOCGIFMAP is deprecated and not - * supported anymore, we need to grab them from procfs - */ - int irq = 0; - char *buffp; - char buff[512]; - char sysname[512]; - FILE *fp; - - if (!strncmp("lo", ifname, strlen("lo"))) - return 0; - - fp = fopen("/proc/interrupts", "r"); - if (!fp) - panic("Cannot open /proc/interrupts!\n"); - - memset(buff, 0, sizeof(buff)); - while (fgets(buff, sizeof(buff), fp) != NULL) { - buff[sizeof(buff) - 1] = 0; - - if (strstr(buff, ifname) == NULL) - continue; - - buffp = buff; - while (*buffp != ':') - buffp++; - *buffp = 0; - irq = atoi(buff); - - memset(buff, 0, sizeof(buff)); - } - - fclose(fp); - - if (irq != 0) - return irq; - /* - * Try sysfs as fallback. Probably wireless devices will be found - * here. We return silently if it fails ... - */ - slprintf(sysname, sizeof(sysname), "/sys/class/net/%s/device/irq", - ifname); - - fp = fopen(sysname, "r"); - if (!fp) - return -ENOENT; - - memset(buff, 0, sizeof(buff)); - if(fgets(buff, sizeof(buff), fp) != NULL) { - buff[sizeof(buff) - 1] = 0; - irq = atoi(buff); - } - - fclose(fp); - - return irq; -} - -int device_set_irq_affinity_list(int irq, unsigned long from, unsigned long to) -{ - int ret, fd; - char file[256], list[64]; - - slprintf(file, sizeof(file), "/proc/irq/%d/smp_affinity_list", irq); - slprintf(list, sizeof(list), "%lu-%lu\n", from, to); - - fd = open(file, O_WRONLY); - if (fd < 0) - return -ENOENT; - - ret = write(fd, list, strlen(list)); - - close(fd); - return ret; -} - -int device_bind_irq_to_cpu(int irq, int cpu) -{ - int ret; - char buff[256]; - char file[256]; - FILE *fp; - - /* Note: first CPU begins with CPU 0 */ - if (irq < 0 || cpu < 0) - return -EINVAL; - - memset(file, 0, sizeof(file)); - memset(buff, 0, sizeof(buff)); - - /* smp_affinity starts counting with CPU 1, 2, ... */ - cpu = cpu + 1; - sprintf(file, "/proc/irq/%d/smp_affinity", irq); - - fp = fopen(file, "w"); - if (!fp) - return -ENOENT; - - sprintf(buff, "%d", cpu); - ret = fwrite(buff, sizeof(buff), 1, fp); - - fclose(fp); - return (ret > 0 ? 0 : ret); -} - void sock_print_net_stats(int sock) { int ret; diff --git a/xutils.h b/xutils.h index 6e72b5c..28a307b 100644 --- a/xutils.h +++ b/xutils.h @@ -36,9 +36,6 @@ extern int ethtool_drvinf(const char *ifname, struct ethtool_drvinfo *drvinf); extern int ethtool_link(const char *ifname); extern int device_mtu(const char *ifname); extern int device_address(const char *ifname, int af, struct sockaddr_storage *ss); -extern int device_irq_number(const char *ifname); -extern int device_set_irq_affinity_list(int irq, unsigned long from, unsigned long to); -extern int device_bind_irq_to_cpu(int irq, int cpu); extern void sock_print_net_stats(int sock); extern int device_ifindex(const char *ifname); extern short device_get_flags(const char *ifname); -- cgit v1.2.3-54-g00ecf