-
Notifications
You must be signed in to change notification settings - Fork 10
/
main.c
147 lines (120 loc) · 2.95 KB
/
main.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
#include <linux/version.h>
#include <linux/module.h>
#include "vq.h"
#include "rx.h"
#include "tx.h"
#include "stats.h"
#ifdef QDISC
int eyeq_qdisc_register(void);
void eyeq_qdisc_unregister(void);
#endif
MODULE_AUTHOR("Vimal <[email protected]>");
MODULE_DESCRIPTION("Perf Isolation");
MODULE_VERSION("1");
MODULE_LICENSE("GPL");
char *iso_param_dev;
MODULE_PARM_DESC(iso_param_dev, "Interface to operate perfiso.");
module_param(iso_param_dev, charp, 0);
/* This is the main device (should be in the root ns) to be used for
* packet tx. We need it irrespective of how packets are classified.
* It will be used to directly transmit feedback packets, without any
* routing. Eventually, we may want a kernel UDP socket, but that's
* for later.
*/
struct net_device *iso_netdev;
static int iso_init(void);
static void iso_exit(void);
void iso_rx_hook_exit(struct iso_rx_context *);
void iso_tx_hook_exit(struct iso_tx_context *);
int iso_exiting;
#ifndef QDISC
/* Current device's GSO size */
static int __prev__ISO_GSO_MAX_SIZE;
#endif
static int iso_init() {
int i, ret = -1;
iso_exiting = 0;
if(iso_param_dev == NULL) {
/*
printk(KERN_INFO "perfiso: need iso_param_dev, the interface to protect.\n");
goto err;
*/
iso_param_dev = "peth2\0";
}
/* trim */
for(i = 0; i < 32 && iso_param_dev[i] != '\0'; i++) {
if(iso_param_dev[i] == '\n') {
iso_param_dev[i] = '\0';
break;
}
}
INIT_LIST_HEAD(&rxctx_list);
INIT_LIST_HEAD(&txctx_list);
if(iso_params_init())
goto out;
if(iso_stats_init())
goto out_1;
#ifdef QDISC
if (eyeq_qdisc_register())
goto out_2;
#else
rcu_read_lock();
iso_netdev = dev_get_by_name(&init_net, iso_param_dev);
rcu_read_unlock();
if(iso_netdev == NULL) {
printk(KERN_INFO "perfiso: device %s not found", iso_param_dev);
goto out_3;
}
global_rxcontext.netdev = iso_netdev;
global_txcontext.netdev = iso_netdev;
if (iso_rx_init(&global_rxcontext))
goto out_4;
if (iso_tx_init(&global_txcontext))
goto out_5;
printk(KERN_INFO "perfiso: operating on %s (%p)\n",
iso_param_dev, iso_netdev);
__prev__ISO_GSO_MAX_SIZE = iso_netdev->gso_max_size;
netif_set_gso_max_size(iso_netdev, ISO_GSO_MAX_SIZE);
#endif
ret = 0;
goto out;
#ifndef QDISC
/* Free up resources */
iso_tx_exit(&global_txcontext);
out_5:
iso_rx_exit(&global_rxcontext);
out_4:
dev_put(iso_netdev);
out_3:
#else
eyeq_qdisc_unregister();
out_2:
#endif
iso_stats_exit();
out_1:
iso_params_exit();
out:
return ret;
}
static void iso_exit() {
iso_exiting = 1;
mb();
iso_stats_exit();
iso_params_exit();
#ifdef QDISC
eyeq_qdisc_unregister();
#else
iso_tx_hook_exit(&global_txcontext);
iso_rx_hook_exit(&global_rxcontext);
iso_tx_exit(&global_txcontext);
iso_rx_exit(&global_rxcontext);
netif_set_gso_max_size(iso_netdev, __prev__ISO_GSO_MAX_SIZE);
dev_put(iso_netdev);
#endif
printk(KERN_INFO "perfiso: goodbye.\n");
}
module_init(iso_init);
module_exit(iso_exit);
/* Local Variables: */
/* indent-tabs-mode:t */
/* End: */