.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * Generic HDLC support routines for Linux |
---|
3 | 4 | * Frame Relay support |
---|
4 | 5 | * |
---|
5 | 6 | * Copyright (C) 1999 - 2006 Krzysztof Halasa <khc@pm.waw.pl> |
---|
6 | | - * |
---|
7 | | - * This program is free software; you can redistribute it and/or modify it |
---|
8 | | - * under the terms of version 2 of the GNU General Public License |
---|
9 | | - * as published by the Free Software Foundation. |
---|
10 | 7 | * |
---|
11 | 8 | |
---|
12 | 9 | Theory of PVC state |
---|
.. | .. |
---|
274 | 271 | } |
---|
275 | 272 | |
---|
276 | 273 | |
---|
277 | | -static int fr_hard_header(struct sk_buff **skb_p, u16 dlci) |
---|
| 274 | +static int fr_hard_header(struct sk_buff *skb, u16 dlci) |
---|
278 | 275 | { |
---|
279 | | - struct sk_buff *skb = *skb_p; |
---|
280 | | - |
---|
281 | 276 | if (!skb->dev) { /* Control packets */ |
---|
282 | 277 | switch (dlci) { |
---|
283 | 278 | case LMI_CCITT_ANSI_DLCI: |
---|
.. | .. |
---|
319 | 314 | } |
---|
320 | 315 | |
---|
321 | 316 | } else if (skb->dev->type == ARPHRD_ETHER) { |
---|
322 | | - if (skb_headroom(skb) < 10) { |
---|
323 | | - struct sk_buff *skb2 = skb_realloc_headroom(skb, 10); |
---|
324 | | - if (!skb2) |
---|
325 | | - return -ENOBUFS; |
---|
326 | | - dev_kfree_skb(skb); |
---|
327 | | - skb = *skb_p = skb2; |
---|
328 | | - } |
---|
329 | 317 | skb_push(skb, 10); |
---|
330 | 318 | skb->data[3] = FR_PAD; |
---|
331 | 319 | skb->data[4] = NLPID_SNAP; |
---|
.. | .. |
---|
419 | 407 | { |
---|
420 | 408 | struct pvc_device *pvc = dev->ml_priv; |
---|
421 | 409 | |
---|
422 | | - if (pvc->state.active) { |
---|
423 | | - if (dev->type == ARPHRD_ETHER) { |
---|
424 | | - int pad = ETH_ZLEN - skb->len; |
---|
425 | | - if (pad > 0) { /* Pad the frame with zeros */ |
---|
426 | | - int len = skb->len; |
---|
427 | | - if (skb_tailroom(skb) < pad) |
---|
428 | | - if (pskb_expand_head(skb, 0, pad, |
---|
429 | | - GFP_ATOMIC)) { |
---|
430 | | - dev->stats.tx_dropped++; |
---|
431 | | - dev_kfree_skb(skb); |
---|
432 | | - return NETDEV_TX_OK; |
---|
433 | | - } |
---|
434 | | - skb_put(skb, pad); |
---|
435 | | - memset(skb->data + len, 0, pad); |
---|
436 | | - } |
---|
437 | | - } |
---|
438 | | - skb->dev = dev; |
---|
439 | | - if (!fr_hard_header(&skb, pvc->dlci)) { |
---|
440 | | - dev->stats.tx_bytes += skb->len; |
---|
441 | | - dev->stats.tx_packets++; |
---|
442 | | - if (pvc->state.fecn) /* TX Congestion counter */ |
---|
443 | | - dev->stats.tx_compressed++; |
---|
444 | | - skb->dev = pvc->frad; |
---|
445 | | - skb->protocol = htons(ETH_P_HDLC); |
---|
446 | | - skb_reset_network_header(skb); |
---|
447 | | - dev_queue_xmit(skb); |
---|
448 | | - return NETDEV_TX_OK; |
---|
| 410 | + if (!pvc->state.active) |
---|
| 411 | + goto drop; |
---|
| 412 | + |
---|
| 413 | + if (dev->type == ARPHRD_ETHER) { |
---|
| 414 | + int pad = ETH_ZLEN - skb->len; |
---|
| 415 | + |
---|
| 416 | + if (pad > 0) { /* Pad the frame with zeros */ |
---|
| 417 | + if (__skb_pad(skb, pad, false)) |
---|
| 418 | + goto drop; |
---|
| 419 | + skb_put(skb, pad); |
---|
449 | 420 | } |
---|
450 | 421 | } |
---|
451 | 422 | |
---|
| 423 | + /* We already requested the header space with dev->needed_headroom. |
---|
| 424 | + * So this is just a protection in case the upper layer didn't take |
---|
| 425 | + * dev->needed_headroom into consideration. |
---|
| 426 | + */ |
---|
| 427 | + if (skb_headroom(skb) < 10) { |
---|
| 428 | + struct sk_buff *skb2 = skb_realloc_headroom(skb, 10); |
---|
| 429 | + |
---|
| 430 | + if (!skb2) |
---|
| 431 | + goto drop; |
---|
| 432 | + dev_kfree_skb(skb); |
---|
| 433 | + skb = skb2; |
---|
| 434 | + } |
---|
| 435 | + |
---|
| 436 | + skb->dev = dev; |
---|
| 437 | + if (fr_hard_header(skb, pvc->dlci)) |
---|
| 438 | + goto drop; |
---|
| 439 | + |
---|
| 440 | + dev->stats.tx_bytes += skb->len; |
---|
| 441 | + dev->stats.tx_packets++; |
---|
| 442 | + if (pvc->state.fecn) /* TX Congestion counter */ |
---|
| 443 | + dev->stats.tx_compressed++; |
---|
| 444 | + skb->dev = pvc->frad; |
---|
| 445 | + skb->protocol = htons(ETH_P_HDLC); |
---|
| 446 | + skb_reset_network_header(skb); |
---|
| 447 | + dev_queue_xmit(skb); |
---|
| 448 | + return NETDEV_TX_OK; |
---|
| 449 | + |
---|
| 450 | +drop: |
---|
452 | 451 | dev->stats.tx_dropped++; |
---|
453 | | - dev_kfree_skb(skb); |
---|
| 452 | + kfree_skb(skb); |
---|
454 | 453 | return NETDEV_TX_OK; |
---|
455 | 454 | } |
---|
456 | 455 | |
---|
.. | .. |
---|
503 | 502 | memset(skb->data, 0, len); |
---|
504 | 503 | skb_reserve(skb, 4); |
---|
505 | 504 | if (lmi == LMI_CISCO) { |
---|
506 | | - fr_hard_header(&skb, LMI_CISCO_DLCI); |
---|
| 505 | + fr_hard_header(skb, LMI_CISCO_DLCI); |
---|
507 | 506 | } else { |
---|
508 | | - fr_hard_header(&skb, LMI_CCITT_ANSI_DLCI); |
---|
| 507 | + fr_hard_header(skb, LMI_CCITT_ANSI_DLCI); |
---|
509 | 508 | } |
---|
510 | 509 | data = skb_tail_pointer(skb); |
---|
511 | 510 | data[i++] = LMI_CALLREF; |
---|