summaryrefslogtreecommitdiff
path: root/irq.c
diff options
context:
space:
mode:
authorDaniel Borkmann <dborkman@redhat.com>2013-06-03 22:49:19 +0200
committerDaniel Borkmann <dborkman@redhat.com>2013-06-03 22:52:33 +0200
commitdc5f7a04f2b446b5224be356c2fc79e88a5d3e8f (patch)
tree1bde4c8eea045e789ea797117e7ab3b84aac7117 /irq.c
parent0bc86fe938e8f6d12aca41a283491f51729d5c62 (diff)
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 <dborkman@redhat.com>
Diffstat (limited to 'irq.c')
-rw-r--r--irq.c129
1 files changed, 129 insertions, 0 deletions
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 <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#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);
+}