Skip to content

Commit 514e115

Browse files
Xie Hedavem330
authored andcommitted
net: x25: Queue received packets in the drivers instead of per-CPU queues
X.25 Layer 3 (the Packet Layer) expects layer 2 to provide a reliable datalink service such that no packets are reordered or dropped. And X.25 Layer 2 (the LAPB layer) is indeed designed to provide such service. However, this reliability is not preserved when a driver calls "netif_rx" to deliver the received packets to layer 3, because "netif_rx" will put the packets into per-CPU queues before they are delivered to layer 3. If there are multiple CPUs, the order of the packets may not be preserved. The per-CPU queues may also drop packets if there are too many. Therefore, we should not call "netif_rx" to let it queue the packets. Instead, we should use our own queue that won't reorder or drop packets. This patch changes all X.25 drivers to use their own queues instead of calling "netif_rx". The patch also documents this requirement in the "x25-iface" documentation. Cc: Martin Schiller <ms@dev.tdt.de> Signed-off-by: Xie He <xie.he.0141@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 7d42e84 commit 514e115

File tree

3 files changed

+80
-64
lines changed

3 files changed

+80
-64
lines changed

Documentation/networking/x25-iface.rst

Lines changed: 9 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -70,60 +70,13 @@ First Byte = 0x03 (X25_IFACE_PARAMS)
7070
LAPB parameters. To be defined.
7171

7272

73+
Requirements for the device driver
74+
----------------------------------
7375

74-
Possible Problems
75-
=================
76-
77-
(Henner Eisen, 2000-10-28)
78-
79-
The X.25 packet layer protocol depends on a reliable datalink service.
80-
The LAPB protocol provides such reliable service. But this reliability
81-
is not preserved by the Linux network device driver interface:
82-
83-
- With Linux 2.4.x (and above) SMP kernels, packet ordering is not
84-
preserved. Even if a device driver calls netif_rx(skb1) and later
85-
netif_rx(skb2), skb2 might be delivered to the network layer
86-
earlier that skb1.
87-
- Data passed upstream by means of netif_rx() might be dropped by the
88-
kernel if the backlog queue is congested.
89-
90-
The X.25 packet layer protocol will detect this and reset the virtual
91-
call in question. But many upper layer protocols are not designed to
92-
handle such N-Reset events gracefully. And frequent N-Reset events
93-
will always degrade performance.
94-
95-
Thus, driver authors should make netif_rx() as reliable as possible:
96-
97-
SMP re-ordering will not occur if the driver's interrupt handler is
98-
always executed on the same CPU. Thus,
99-
100-
- Driver authors should use irq affinity for the interrupt handler.
101-
102-
The probability of packet loss due to backlog congestion can be
103-
reduced by the following measures or a combination thereof:
104-
105-
(1) Drivers for kernel versions 2.4.x and above should always check the
106-
return value of netif_rx(). If it returns NET_RX_DROP, the
107-
driver's LAPB protocol must not confirm reception of the frame
108-
to the peer.
109-
This will reliably suppress packet loss. The LAPB protocol will
110-
automatically cause the peer to re-transmit the dropped packet
111-
later.
112-
The lapb module interface was modified to support this. Its
113-
data_indication() method should now transparently pass the
114-
netif_rx() return value to the (lapb module) caller.
115-
(2) Drivers for kernel versions 2.2.x should always check the global
116-
variable netdev_dropping when a new frame is received. The driver
117-
should only call netif_rx() if netdev_dropping is zero. Otherwise
118-
the driver should not confirm delivery of the frame and drop it.
119-
Alternatively, the driver can queue the frame internally and call
120-
netif_rx() later when netif_dropping is 0 again. In that case, delivery
121-
confirmation should also be deferred such that the internal queue
122-
cannot grow to much.
123-
This will not reliably avoid packet loss, but the probability
124-
of packet loss in netif_rx() path will be significantly reduced.
125-
(3) Additionally, driver authors might consider to support
126-
CONFIG_NET_HW_FLOWCONTROL. This allows the driver to be woken up
127-
when a previously congested backlog queue becomes empty again.
128-
The driver could uses this for flow-controlling the peer by means
129-
of the LAPB protocol's flow-control service.
76+
Packets should not be reordered or dropped when delivering between the
77+
Packet Layer and the device driver.
78+
79+
To avoid packets from being reordered or dropped when delivering from
80+
the device driver to the Packet Layer, the device driver should not
81+
call "netif_rx" to deliver the received packets. Instead, it should
82+
call "netif_receive_skb_core" from softirq context to deliver them.

drivers/net/wan/hdlc_x25.c

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ struct x25_state {
2525
x25_hdlc_proto settings;
2626
bool up;
2727
spinlock_t up_lock; /* Protects "up" */
28+
struct sk_buff_head rx_queue;
29+
struct tasklet_struct rx_tasklet;
2830
};
2931

3032
static int x25_ioctl(struct net_device *dev, struct ifreq *ifr);
@@ -34,14 +36,27 @@ static struct x25_state *state(hdlc_device *hdlc)
3436
return hdlc->state;
3537
}
3638

39+
static void x25_rx_queue_kick(struct tasklet_struct *t)
40+
{
41+
struct x25_state *x25st = from_tasklet(x25st, t, rx_tasklet);
42+
struct sk_buff *skb = skb_dequeue(&x25st->rx_queue);
43+
44+
while (skb) {
45+
netif_receive_skb_core(skb);
46+
skb = skb_dequeue(&x25st->rx_queue);
47+
}
48+
}
49+
3750
/* These functions are callbacks called by LAPB layer */
3851

3952
static void x25_connect_disconnect(struct net_device *dev, int reason, int code)
4053
{
54+
struct x25_state *x25st = state(dev_to_hdlc(dev));
4155
struct sk_buff *skb;
4256
unsigned char *ptr;
4357

44-
if ((skb = dev_alloc_skb(1)) == NULL) {
58+
skb = __dev_alloc_skb(1, GFP_ATOMIC | __GFP_NOMEMALLOC);
59+
if (!skb) {
4560
netdev_err(dev, "out of memory\n");
4661
return;
4762
}
@@ -50,7 +65,9 @@ static void x25_connect_disconnect(struct net_device *dev, int reason, int code)
5065
*ptr = code;
5166

5267
skb->protocol = x25_type_trans(skb, dev);
53-
netif_rx(skb);
68+
69+
skb_queue_tail(&x25st->rx_queue, skb);
70+
tasklet_schedule(&x25st->rx_tasklet);
5471
}
5572

5673

@@ -71,6 +88,7 @@ static void x25_disconnected(struct net_device *dev, int reason)
7188

7289
static int x25_data_indication(struct net_device *dev, struct sk_buff *skb)
7390
{
91+
struct x25_state *x25st = state(dev_to_hdlc(dev));
7492
unsigned char *ptr;
7593

7694
if (skb_cow(skb, 1)) {
@@ -84,7 +102,10 @@ static int x25_data_indication(struct net_device *dev, struct sk_buff *skb)
84102
*ptr = X25_IFACE_DATA;
85103

86104
skb->protocol = x25_type_trans(skb, dev);
87-
return netif_rx(skb);
105+
106+
skb_queue_tail(&x25st->rx_queue, skb);
107+
tasklet_schedule(&x25st->rx_tasklet);
108+
return NET_RX_SUCCESS;
88109
}
89110

90111

@@ -223,6 +244,7 @@ static void x25_close(struct net_device *dev)
223244
spin_unlock_bh(&x25st->up_lock);
224245

225246
lapb_unregister(dev);
247+
tasklet_kill(&x25st->rx_tasklet);
226248
}
227249

228250

@@ -338,6 +360,8 @@ static int x25_ioctl(struct net_device *dev, struct ifreq *ifr)
338360
memcpy(&state(hdlc)->settings, &new_settings, size);
339361
state(hdlc)->up = false;
340362
spin_lock_init(&state(hdlc)->up_lock);
363+
skb_queue_head_init(&state(hdlc)->rx_queue);
364+
tasklet_setup(&state(hdlc)->rx_tasklet, x25_rx_queue_kick);
341365

342366
/* There's no header_ops so hard_header_len should be 0. */
343367
dev->hard_header_len = 0;

drivers/net/wan/lapbether.c

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ struct lapbethdev {
5353
struct net_device *axdev; /* lapbeth device (lapb#) */
5454
bool up;
5555
spinlock_t up_lock; /* Protects "up" */
56+
struct sk_buff_head rx_queue;
57+
struct napi_struct napi;
5658
};
5759

5860
static LIST_HEAD(lapbeth_devices);
@@ -83,6 +85,26 @@ static __inline__ int dev_is_ethdev(struct net_device *dev)
8385

8486
/* ------------------------------------------------------------------------ */
8587

88+
static int lapbeth_napi_poll(struct napi_struct *napi, int budget)
89+
{
90+
struct lapbethdev *lapbeth = container_of(napi, struct lapbethdev,
91+
napi);
92+
struct sk_buff *skb;
93+
int processed = 0;
94+
95+
for (; processed < budget; ++processed) {
96+
skb = skb_dequeue(&lapbeth->rx_queue);
97+
if (!skb)
98+
break;
99+
netif_receive_skb_core(skb);
100+
}
101+
102+
if (processed < budget)
103+
napi_complete(napi);
104+
105+
return processed;
106+
}
107+
86108
/*
87109
* Receive a LAPB frame via an ethernet interface.
88110
*/
@@ -135,6 +157,7 @@ static int lapbeth_rcv(struct sk_buff *skb, struct net_device *dev, struct packe
135157

136158
static int lapbeth_data_indication(struct net_device *dev, struct sk_buff *skb)
137159
{
160+
struct lapbethdev *lapbeth = netdev_priv(dev);
138161
unsigned char *ptr;
139162

140163
if (skb_cow(skb, 1)) {
@@ -148,7 +171,10 @@ static int lapbeth_data_indication(struct net_device *dev, struct sk_buff *skb)
148171
*ptr = X25_IFACE_DATA;
149172

150173
skb->protocol = x25_type_trans(skb, dev);
151-
return netif_rx(skb);
174+
175+
skb_queue_tail(&lapbeth->rx_queue, skb);
176+
napi_schedule(&lapbeth->napi);
177+
return NET_RX_SUCCESS;
152178
}
153179

154180
/*
@@ -233,8 +259,9 @@ static void lapbeth_data_transmit(struct net_device *ndev, struct sk_buff *skb)
233259

234260
static void lapbeth_connected(struct net_device *dev, int reason)
235261
{
262+
struct lapbethdev *lapbeth = netdev_priv(dev);
236263
unsigned char *ptr;
237-
struct sk_buff *skb = dev_alloc_skb(1);
264+
struct sk_buff *skb = __dev_alloc_skb(1, GFP_ATOMIC | __GFP_NOMEMALLOC);
238265

239266
if (!skb) {
240267
pr_err("out of memory\n");
@@ -245,13 +272,16 @@ static void lapbeth_connected(struct net_device *dev, int reason)
245272
*ptr = X25_IFACE_CONNECT;
246273

247274
skb->protocol = x25_type_trans(skb, dev);
248-
netif_rx(skb);
275+
276+
skb_queue_tail(&lapbeth->rx_queue, skb);
277+
napi_schedule(&lapbeth->napi);
249278
}
250279

251280
static void lapbeth_disconnected(struct net_device *dev, int reason)
252281
{
282+
struct lapbethdev *lapbeth = netdev_priv(dev);
253283
unsigned char *ptr;
254-
struct sk_buff *skb = dev_alloc_skb(1);
284+
struct sk_buff *skb = __dev_alloc_skb(1, GFP_ATOMIC | __GFP_NOMEMALLOC);
255285

256286
if (!skb) {
257287
pr_err("out of memory\n");
@@ -262,7 +292,9 @@ static void lapbeth_disconnected(struct net_device *dev, int reason)
262292
*ptr = X25_IFACE_DISCONNECT;
263293

264294
skb->protocol = x25_type_trans(skb, dev);
265-
netif_rx(skb);
295+
296+
skb_queue_tail(&lapbeth->rx_queue, skb);
297+
napi_schedule(&lapbeth->napi);
266298
}
267299

268300
/*
@@ -293,6 +325,8 @@ static int lapbeth_open(struct net_device *dev)
293325
struct lapbethdev *lapbeth = netdev_priv(dev);
294326
int err;
295327

328+
napi_enable(&lapbeth->napi);
329+
296330
if ((err = lapb_register(dev, &lapbeth_callbacks)) != LAPB_OK) {
297331
pr_err("lapb_register error: %d\n", err);
298332
return -ENODEV;
@@ -317,6 +351,8 @@ static int lapbeth_close(struct net_device *dev)
317351
if ((err = lapb_unregister(dev)) != LAPB_OK)
318352
pr_err("lapb_unregister error: %d\n", err);
319353

354+
napi_disable(&lapbeth->napi);
355+
320356
return 0;
321357
}
322358

@@ -374,6 +410,9 @@ static int lapbeth_new_device(struct net_device *dev)
374410
lapbeth->up = false;
375411
spin_lock_init(&lapbeth->up_lock);
376412

413+
skb_queue_head_init(&lapbeth->rx_queue);
414+
netif_napi_add(ndev, &lapbeth->napi, lapbeth_napi_poll, 16);
415+
377416
rc = -EIO;
378417
if (register_netdevice(ndev))
379418
goto fail;

0 commit comments

Comments
 (0)