rmnet_map_data.c 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. /* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
  2. *
  3. * This program is free software; you can redistribute it and/or modify
  4. * it under the terms of the GNU General Public License version 2 and
  5. * only version 2 as published by the Free Software Foundation.
  6. *
  7. * This program is distributed in the hope that it will be useful,
  8. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. * GNU General Public License for more details.
  11. *
  12. * RMNET Data MAP protocol
  13. *
  14. */
  15. #include <linux/netdevice.h>
  16. #include "rmnet_config.h"
  17. #include "rmnet_map.h"
  18. #include "rmnet_private.h"
  19. #define RMNET_MAP_DEAGGR_SPACING 64
  20. #define RMNET_MAP_DEAGGR_HEADROOM (RMNET_MAP_DEAGGR_SPACING / 2)
  21. /* Adds MAP header to front of skb->data
  22. * Padding is calculated and set appropriately in MAP header. Mux ID is
  23. * initialized to 0.
  24. */
  25. struct rmnet_map_header *rmnet_map_add_map_header(struct sk_buff *skb,
  26. int hdrlen, int pad)
  27. {
  28. struct rmnet_map_header *map_header;
  29. u32 padding, map_datalen;
  30. u8 *padbytes;
  31. if (skb_headroom(skb) < sizeof(struct rmnet_map_header))
  32. return NULL;
  33. map_datalen = skb->len - hdrlen;
  34. map_header = (struct rmnet_map_header *)
  35. skb_push(skb, sizeof(struct rmnet_map_header));
  36. memset(map_header, 0, sizeof(struct rmnet_map_header));
  37. if (pad == RMNET_MAP_NO_PAD_BYTES) {
  38. map_header->pkt_len = htons(map_datalen);
  39. return map_header;
  40. }
  41. padding = ALIGN(map_datalen, 4) - map_datalen;
  42. if (padding == 0)
  43. goto done;
  44. if (skb_tailroom(skb) < padding)
  45. return NULL;
  46. padbytes = (u8 *)skb_put(skb, padding);
  47. memset(padbytes, 0, padding);
  48. done:
  49. map_header->pkt_len = htons(map_datalen + padding);
  50. map_header->pad_len = padding & 0x3F;
  51. return map_header;
  52. }
  53. /* Deaggregates a single packet
  54. * A whole new buffer is allocated for each portion of an aggregated frame.
  55. * Caller should keep calling deaggregate() on the source skb until 0 is
  56. * returned, indicating that there are no more packets to deaggregate. Caller
  57. * is responsible for freeing the original skb.
  58. */
  59. struct sk_buff *rmnet_map_deaggregate(struct sk_buff *skb)
  60. {
  61. struct rmnet_map_header *maph;
  62. struct sk_buff *skbn;
  63. u32 packet_len;
  64. if (skb->len == 0)
  65. return NULL;
  66. maph = (struct rmnet_map_header *)skb->data;
  67. packet_len = ntohs(maph->pkt_len) + sizeof(struct rmnet_map_header);
  68. if (((int)skb->len - (int)packet_len) < 0)
  69. return NULL;
  70. /* Some hardware can send us empty frames. Catch them */
  71. if (ntohs(maph->pkt_len) == 0)
  72. return NULL;
  73. skbn = alloc_skb(packet_len + RMNET_MAP_DEAGGR_SPACING, GFP_ATOMIC);
  74. if (!skbn)
  75. return NULL;
  76. skbn->dev = skb->dev;
  77. skb_reserve(skbn, RMNET_MAP_DEAGGR_HEADROOM);
  78. skb_put(skbn, packet_len);
  79. memcpy(skbn->data, skb->data, packet_len);
  80. skb_pull(skb, packet_len);
  81. return skbn;
  82. }