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#include <linux/module.h>
31#include <linux/kernel.h>
32#include <linux/netdevice.h>
33#include <linux/etherdevice.h>
34#include <linux/init.h>
35#include <linux/interrupt.h>
36#include <linux/moduleparam.h>
37#include <net/pkt_sched.h>
38#include <net/net_namespace.h>
39
40#define TX_Q_LIMIT 32
41struct ifb_q_private {
42 struct net_device *dev;
43 struct tasklet_struct ifb_tasklet;
44 int tasklet_pending;
45 int txqnum;
46 struct sk_buff_head rq;
47 u64 rx_packets;
48 u64 rx_bytes;
49 struct u64_stats_sync rsync;
50
51 struct u64_stats_sync tsync;
52 u64 tx_packets;
53 u64 tx_bytes;
54 struct sk_buff_head tq;
55} ____cacheline_aligned_in_smp;
56
57struct ifb_dev_private {
58 struct ifb_q_private *tx_private;
59};
60
61static netdev_tx_t ifb_xmit(struct sk_buff *skb, struct net_device *dev);
62static int ifb_open(struct net_device *dev);
63static int ifb_close(struct net_device *dev);
64
65static void ifb_ri_tasklet(unsigned long _txp)
66{
67 struct ifb_q_private *txp = (struct ifb_q_private *)_txp;
68 struct netdev_queue *txq;
69 struct sk_buff *skb;
70
71 txq = netdev_get_tx_queue(txp->dev, txp->txqnum);
72 skb = skb_peek(&txp->tq);
73 if (!skb) {
74 if (!__netif_tx_trylock(txq))
75 goto resched;
76 skb_queue_splice_tail_init(&txp->rq, &txp->tq);
77 __netif_tx_unlock(txq);
78 }
79
80 while ((skb = __skb_dequeue(&txp->tq)) != NULL) {
81 skb->tc_redirected = 0;
82 skb->tc_skip_classify = 1;
83
84 u64_stats_update_begin(&txp->tsync);
85 txp->tx_packets++;
86 txp->tx_bytes += skb->len;
87 u64_stats_update_end(&txp->tsync);
88
89 rcu_read_lock();
90 skb->dev = dev_get_by_index_rcu(dev_net(txp->dev), skb->skb_iif);
91 if (!skb->dev) {
92 rcu_read_unlock();
93 dev_kfree_skb(skb);
94 txp->dev->stats.tx_dropped++;
95 if (skb_queue_len(&txp->tq) != 0)
96 goto resched;
97 break;
98 }
99 rcu_read_unlock();
100 skb->skb_iif = txp->dev->ifindex;
101
102 if (!skb->tc_from_ingress) {
103 dev_queue_xmit(skb);
104 } else {
105 skb_pull_rcsum(skb, skb->mac_len);
106 netif_receive_skb(skb);
107 }
108 }
109
110 if (__netif_tx_trylock(txq)) {
111 skb = skb_peek(&txp->rq);
112 if (!skb) {
113 txp->tasklet_pending = 0;
114 if (netif_tx_queue_stopped(txq))
115 netif_tx_wake_queue(txq);
116 } else {
117 __netif_tx_unlock(txq);
118 goto resched;
119 }
120 __netif_tx_unlock(txq);
121 } else {
122resched:
123 txp->tasklet_pending = 1;
124 tasklet_schedule(&txp->ifb_tasklet);
125 }
126
127}
128
129static void ifb_stats64(struct net_device *dev,
130 struct rtnl_link_stats64 *stats)
131{
132 struct ifb_dev_private *dp = netdev_priv(dev);
133 struct ifb_q_private *txp = dp->tx_private;
134 unsigned int start;
135 u64 packets, bytes;
136 int i;
137
138 for (i = 0; i < dev->num_tx_queues; i++,txp++) {
139 do {
140 start = u64_stats_fetch_begin_irq(&txp->rsync);
141 packets = txp->rx_packets;
142 bytes = txp->rx_bytes;
143 } while (u64_stats_fetch_retry_irq(&txp->rsync, start));
144 stats->rx_packets += packets;
145 stats->rx_bytes += bytes;
146
147 do {
148 start = u64_stats_fetch_begin_irq(&txp->tsync);
149 packets = txp->tx_packets;
150 bytes = txp->tx_bytes;
151 } while (u64_stats_fetch_retry_irq(&txp->tsync, start));
152 stats->tx_packets += packets;
153 stats->tx_bytes += bytes;
154 }
155 stats->rx_dropped = dev->stats.rx_dropped;
156 stats->tx_dropped = dev->stats.tx_dropped;
157}
158
159static int ifb_dev_init(struct net_device *dev)
160{
161 struct ifb_dev_private *dp = netdev_priv(dev);
162 struct ifb_q_private *txp;
163 int i;
164
165 txp = kcalloc(dev->num_tx_queues, sizeof(*txp), GFP_KERNEL);
166 if (!txp)
167 return -ENOMEM;
168 dp->tx_private = txp;
169 for (i = 0; i < dev->num_tx_queues; i++,txp++) {
170 txp->txqnum = i;
171 txp->dev = dev;
172 __skb_queue_head_init(&txp->rq);
173 __skb_queue_head_init(&txp->tq);
174 u64_stats_init(&txp->rsync);
175 u64_stats_init(&txp->tsync);
176 tasklet_init(&txp->ifb_tasklet, ifb_ri_tasklet,
177 (unsigned long)txp);
178 netif_tx_start_queue(netdev_get_tx_queue(dev, i));
179 }
180 return 0;
181}
182
183static const struct net_device_ops ifb_netdev_ops = {
184 .ndo_open = ifb_open,
185 .ndo_stop = ifb_close,
186 .ndo_get_stats64 = ifb_stats64,
187 .ndo_start_xmit = ifb_xmit,
188 .ndo_validate_addr = eth_validate_addr,
189 .ndo_init = ifb_dev_init,
190};
191
192#define IFB_FEATURES (NETIF_F_HW_CSUM | NETIF_F_SG | NETIF_F_FRAGLIST | \
193 NETIF_F_TSO_ECN | NETIF_F_TSO | NETIF_F_TSO6 | \
194 NETIF_F_GSO_ENCAP_ALL | \
195 NETIF_F_HIGHDMA | NETIF_F_HW_VLAN_CTAG_TX | \
196 NETIF_F_HW_VLAN_STAG_TX)
197
198static void ifb_dev_free(struct net_device *dev)
199{
200 struct ifb_dev_private *dp = netdev_priv(dev);
201 struct ifb_q_private *txp = dp->tx_private;
202 int i;
203
204 for (i = 0; i < dev->num_tx_queues; i++,txp++) {
205 tasklet_kill(&txp->ifb_tasklet);
206 __skb_queue_purge(&txp->rq);
207 __skb_queue_purge(&txp->tq);
208 }
209 kfree(dp->tx_private);
210}
211
212static void ifb_setup(struct net_device *dev)
213{
214
215 dev->netdev_ops = &ifb_netdev_ops;
216
217
218 ether_setup(dev);
219 dev->tx_queue_len = TX_Q_LIMIT;
220
221 dev->features |= IFB_FEATURES;
222 dev->hw_features |= dev->features;
223 dev->hw_enc_features |= dev->features;
224 dev->vlan_features |= IFB_FEATURES & ~(NETIF_F_HW_VLAN_CTAG_TX |
225 NETIF_F_HW_VLAN_STAG_TX);
226
227 dev->flags |= IFF_NOARP;
228 dev->flags &= ~IFF_MULTICAST;
229 dev->priv_flags &= ~IFF_TX_SKB_SHARING;
230 netif_keep_dst(dev);
231 eth_hw_addr_random(dev);
232 dev->needs_free_netdev = true;
233 dev->priv_destructor = ifb_dev_free;
234
235 dev->min_mtu = 0;
236 dev->max_mtu = 0;
237}
238
239static netdev_tx_t ifb_xmit(struct sk_buff *skb, struct net_device *dev)
240{
241 struct ifb_dev_private *dp = netdev_priv(dev);
242 struct ifb_q_private *txp = dp->tx_private + skb_get_queue_mapping(skb);
243
244 u64_stats_update_begin(&txp->rsync);
245 txp->rx_packets++;
246 txp->rx_bytes += skb->len;
247 u64_stats_update_end(&txp->rsync);
248
249 if (!skb->tc_redirected || !skb->skb_iif) {
250 dev_kfree_skb(skb);
251 dev->stats.rx_dropped++;
252 return NETDEV_TX_OK;
253 }
254
255 if (skb_queue_len(&txp->rq) >= dev->tx_queue_len)
256 netif_tx_stop_queue(netdev_get_tx_queue(dev, txp->txqnum));
257
258 __skb_queue_tail(&txp->rq, skb);
259 if (!txp->tasklet_pending) {
260 txp->tasklet_pending = 1;
261 tasklet_schedule(&txp->ifb_tasklet);
262 }
263
264 return NETDEV_TX_OK;
265}
266
267static int ifb_close(struct net_device *dev)
268{
269 netif_tx_stop_all_queues(dev);
270 return 0;
271}
272
273static int ifb_open(struct net_device *dev)
274{
275 netif_tx_start_all_queues(dev);
276 return 0;
277}
278
279static int ifb_validate(struct nlattr *tb[], struct nlattr *data[],
280 struct netlink_ext_ack *extack)
281{
282 if (tb[IFLA_ADDRESS]) {
283 if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN)
284 return -EINVAL;
285 if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS])))
286 return -EADDRNOTAVAIL;
287 }
288 return 0;
289}
290
291static struct rtnl_link_ops ifb_link_ops __read_mostly = {
292 .kind = "ifb",
293 .priv_size = sizeof(struct ifb_dev_private),
294 .setup = ifb_setup,
295 .validate = ifb_validate,
296};
297
298
299
300
301
302static int numifbs = 2;
303module_param(numifbs, int, 0);
304MODULE_PARM_DESC(numifbs, "Number of ifb devices");
305
306static int __init ifb_init_one(int index)
307{
308 struct net_device *dev_ifb;
309 int err;
310
311 dev_ifb = alloc_netdev(sizeof(struct ifb_dev_private), "ifb%d",
312 NET_NAME_UNKNOWN, ifb_setup);
313
314 if (!dev_ifb)
315 return -ENOMEM;
316
317 dev_ifb->rtnl_link_ops = &ifb_link_ops;
318 err = register_netdevice(dev_ifb);
319 if (err < 0)
320 goto err;
321
322 return 0;
323
324err:
325 free_netdev(dev_ifb);
326 return err;
327}
328
329static int __init ifb_init_module(void)
330{
331 int i, err;
332
333 down_write(&pernet_ops_rwsem);
334 rtnl_lock();
335 err = __rtnl_link_register(&ifb_link_ops);
336 if (err < 0)
337 goto out;
338
339 for (i = 0; i < numifbs && !err; i++) {
340 err = ifb_init_one(i);
341 cond_resched();
342 }
343 if (err)
344 __rtnl_link_unregister(&ifb_link_ops);
345
346out:
347 rtnl_unlock();
348 up_write(&pernet_ops_rwsem);
349
350 return err;
351}
352
353static void __exit ifb_cleanup_module(void)
354{
355 rtnl_link_unregister(&ifb_link_ops);
356}
357
358module_init(ifb_init_module);
359module_exit(ifb_cleanup_module);
360MODULE_LICENSE("GPL");
361MODULE_AUTHOR("Jamal Hadi Salim");
362MODULE_ALIAS_RTNL_LINK("ifb");
363