cfpkt_skbuff.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579
  1. /*
  2. * Copyright (C) ST-Ericsson AB 2010
  3. * Author: Sjur Brendeland/sjur.brandeland@stericsson.com
  4. * License terms: GNU General Public License (GPL) version 2
  5. */
  6. #include <linux/string.h>
  7. #include <linux/skbuff.h>
  8. #include <linux/hardirq.h>
  9. #include <net/caif/cfpkt.h>
  10. #define PKT_PREFIX 48
  11. #define PKT_POSTFIX 2
  12. #define PKT_LEN_WHEN_EXTENDING 128
  13. #define PKT_ERROR(pkt, errmsg) do { \
  14. cfpkt_priv(pkt)->erronous = true; \
  15. skb_reset_tail_pointer(&pkt->skb); \
  16. pr_warning("CAIF: " errmsg);\
  17. } while (0)
  18. struct cfpktq {
  19. struct sk_buff_head head;
  20. atomic_t count;
  21. /* Lock protects count updates */
  22. spinlock_t lock;
  23. };
  24. /*
  25. * net/caif/ is generic and does not
  26. * understand SKB, so we do this typecast
  27. */
  28. struct cfpkt {
  29. struct sk_buff skb;
  30. };
  31. /* Private data inside SKB */
  32. struct cfpkt_priv_data {
  33. struct dev_info dev_info;
  34. bool erronous;
  35. };
  36. inline struct cfpkt_priv_data *cfpkt_priv(struct cfpkt *pkt)
  37. {
  38. return (struct cfpkt_priv_data *) pkt->skb.cb;
  39. }
  40. inline bool is_erronous(struct cfpkt *pkt)
  41. {
  42. return cfpkt_priv(pkt)->erronous;
  43. }
  44. inline struct sk_buff *pkt_to_skb(struct cfpkt *pkt)
  45. {
  46. return &pkt->skb;
  47. }
  48. inline struct cfpkt *skb_to_pkt(struct sk_buff *skb)
  49. {
  50. return (struct cfpkt *) skb;
  51. }
  52. struct cfpkt *cfpkt_fromnative(enum caif_direction dir, void *nativepkt)
  53. {
  54. struct cfpkt *pkt = skb_to_pkt(nativepkt);
  55. cfpkt_priv(pkt)->erronous = false;
  56. return pkt;
  57. }
  58. EXPORT_SYMBOL(cfpkt_fromnative);
  59. void *cfpkt_tonative(struct cfpkt *pkt)
  60. {
  61. return (void *) pkt;
  62. }
  63. EXPORT_SYMBOL(cfpkt_tonative);
  64. static struct cfpkt *cfpkt_create_pfx(u16 len, u16 pfx)
  65. {
  66. struct sk_buff *skb;
  67. if (likely(in_interrupt()))
  68. skb = alloc_skb(len + pfx, GFP_ATOMIC);
  69. else
  70. skb = alloc_skb(len + pfx, GFP_KERNEL);
  71. if (unlikely(skb == NULL))
  72. return NULL;
  73. skb_reserve(skb, pfx);
  74. return skb_to_pkt(skb);
  75. }
  76. inline struct cfpkt *cfpkt_create(u16 len)
  77. {
  78. return cfpkt_create_pfx(len + PKT_POSTFIX, PKT_PREFIX);
  79. }
  80. EXPORT_SYMBOL(cfpkt_create);
  81. void cfpkt_destroy(struct cfpkt *pkt)
  82. {
  83. struct sk_buff *skb = pkt_to_skb(pkt);
  84. kfree_skb(skb);
  85. }
  86. EXPORT_SYMBOL(cfpkt_destroy);
  87. inline bool cfpkt_more(struct cfpkt *pkt)
  88. {
  89. struct sk_buff *skb = pkt_to_skb(pkt);
  90. return skb->len > 0;
  91. }
  92. EXPORT_SYMBOL(cfpkt_more);
  93. int cfpkt_peek_head(struct cfpkt *pkt, void *data, u16 len)
  94. {
  95. struct sk_buff *skb = pkt_to_skb(pkt);
  96. if (skb_headlen(skb) >= len) {
  97. memcpy(data, skb->data, len);
  98. return 0;
  99. }
  100. return !cfpkt_extr_head(pkt, data, len) &&
  101. !cfpkt_add_head(pkt, data, len);
  102. }
  103. EXPORT_SYMBOL(cfpkt_peek_head);
  104. int cfpkt_extr_head(struct cfpkt *pkt, void *data, u16 len)
  105. {
  106. struct sk_buff *skb = pkt_to_skb(pkt);
  107. u8 *from;
  108. if (unlikely(is_erronous(pkt)))
  109. return -EPROTO;
  110. if (unlikely(len > skb->len)) {
  111. PKT_ERROR(pkt, "cfpkt_extr_head read beyond end of packet\n");
  112. return -EPROTO;
  113. }
  114. if (unlikely(len > skb_headlen(skb))) {
  115. if (unlikely(skb_linearize(skb) != 0)) {
  116. PKT_ERROR(pkt, "cfpkt_extr_head linearize failed\n");
  117. return -EPROTO;
  118. }
  119. }
  120. from = skb_pull(skb, len);
  121. from -= len;
  122. memcpy(data, from, len);
  123. return 0;
  124. }
  125. EXPORT_SYMBOL(cfpkt_extr_head);
  126. int cfpkt_extr_trail(struct cfpkt *pkt, void *dta, u16 len)
  127. {
  128. struct sk_buff *skb = pkt_to_skb(pkt);
  129. u8 *data = dta;
  130. u8 *from;
  131. if (unlikely(is_erronous(pkt)))
  132. return -EPROTO;
  133. if (unlikely(skb_linearize(skb) != 0)) {
  134. PKT_ERROR(pkt, "cfpkt_extr_trail linearize failed\n");
  135. return -EPROTO;
  136. }
  137. if (unlikely(skb->data + len > skb_tail_pointer(skb))) {
  138. PKT_ERROR(pkt, "cfpkt_extr_trail read beyond end of packet\n");
  139. return -EPROTO;
  140. }
  141. from = skb_tail_pointer(skb) - len;
  142. skb_trim(skb, skb->len - len);
  143. memcpy(data, from, len);
  144. return 0;
  145. }
  146. EXPORT_SYMBOL(cfpkt_extr_trail);
  147. int cfpkt_pad_trail(struct cfpkt *pkt, u16 len)
  148. {
  149. return cfpkt_add_body(pkt, NULL, len);
  150. }
  151. EXPORT_SYMBOL(cfpkt_pad_trail);
  152. int cfpkt_add_body(struct cfpkt *pkt, const void *data, u16 len)
  153. {
  154. struct sk_buff *skb = pkt_to_skb(pkt);
  155. struct sk_buff *lastskb;
  156. u8 *to;
  157. u16 addlen = 0;
  158. if (unlikely(is_erronous(pkt)))
  159. return -EPROTO;
  160. lastskb = skb;
  161. /* Check whether we need to add space at the tail */
  162. if (unlikely(skb_tailroom(skb) < len)) {
  163. if (likely(len < PKT_LEN_WHEN_EXTENDING))
  164. addlen = PKT_LEN_WHEN_EXTENDING;
  165. else
  166. addlen = len;
  167. }
  168. /* Check whether we need to change the SKB before writing to the tail */
  169. if (unlikely((addlen > 0) || skb_cloned(skb) || skb_shared(skb))) {
  170. /* Make sure data is writable */
  171. if (unlikely(skb_cow_data(skb, addlen, &lastskb) < 0)) {
  172. PKT_ERROR(pkt, "cfpkt_add_body: cow failed\n");
  173. return -EPROTO;
  174. }
  175. /*
  176. * Is the SKB non-linear after skb_cow_data()? If so, we are
  177. * going to add data to the last SKB, so we need to adjust
  178. * lengths of the top SKB.
  179. */
  180. if (lastskb != skb) {
  181. pr_warning("CAIF: %s(): Packet is non-linear\n",
  182. __func__);
  183. skb->len += len;
  184. skb->data_len += len;
  185. }
  186. }
  187. /* All set to put the last SKB and optionally write data there. */
  188. to = skb_put(lastskb, len);
  189. if (likely(data))
  190. memcpy(to, data, len);
  191. return 0;
  192. }
  193. EXPORT_SYMBOL(cfpkt_add_body);
  194. inline int cfpkt_addbdy(struct cfpkt *pkt, u8 data)
  195. {
  196. return cfpkt_add_body(pkt, &data, 1);
  197. }
  198. EXPORT_SYMBOL(cfpkt_addbdy);
  199. int cfpkt_add_head(struct cfpkt *pkt, const void *data2, u16 len)
  200. {
  201. struct sk_buff *skb = pkt_to_skb(pkt);
  202. struct sk_buff *lastskb;
  203. u8 *to;
  204. const u8 *data = data2;
  205. int ret;
  206. if (unlikely(is_erronous(pkt)))
  207. return -EPROTO;
  208. if (unlikely(skb_headroom(skb) < len)) {
  209. PKT_ERROR(pkt, "cfpkt_add_head: no headroom\n");
  210. return -EPROTO;
  211. }
  212. /* Make sure data is writable */
  213. ret = skb_cow_data(skb, 0, &lastskb);
  214. if (unlikely(ret < 0)) {
  215. PKT_ERROR(pkt, "cfpkt_add_head: cow failed\n");
  216. return ret;
  217. }
  218. to = skb_push(skb, len);
  219. memcpy(to, data, len);
  220. return 0;
  221. }
  222. EXPORT_SYMBOL(cfpkt_add_head);
  223. inline int cfpkt_add_trail(struct cfpkt *pkt, const void *data, u16 len)
  224. {
  225. return cfpkt_add_body(pkt, data, len);
  226. }
  227. EXPORT_SYMBOL(cfpkt_add_trail);
  228. inline u16 cfpkt_getlen(struct cfpkt *pkt)
  229. {
  230. struct sk_buff *skb = pkt_to_skb(pkt);
  231. return skb->len;
  232. }
  233. EXPORT_SYMBOL(cfpkt_getlen);
  234. inline u16 cfpkt_iterate(struct cfpkt *pkt,
  235. u16 (*iter_func)(u16, void *, u16),
  236. u16 data)
  237. {
  238. /*
  239. * Don't care about the performance hit of linearizing,
  240. * Checksum should not be used on high-speed interfaces anyway.
  241. */
  242. if (unlikely(is_erronous(pkt)))
  243. return -EPROTO;
  244. if (unlikely(skb_linearize(&pkt->skb) != 0)) {
  245. PKT_ERROR(pkt, "cfpkt_iterate: linearize failed\n");
  246. return -EPROTO;
  247. }
  248. return iter_func(data, pkt->skb.data, cfpkt_getlen(pkt));
  249. }
  250. EXPORT_SYMBOL(cfpkt_iterate);
  251. int cfpkt_setlen(struct cfpkt *pkt, u16 len)
  252. {
  253. struct sk_buff *skb = pkt_to_skb(pkt);
  254. if (unlikely(is_erronous(pkt)))
  255. return -EPROTO;
  256. if (likely(len <= skb->len)) {
  257. if (unlikely(skb->data_len))
  258. ___pskb_trim(skb, len);
  259. else
  260. skb_trim(skb, len);
  261. return cfpkt_getlen(pkt);
  262. }
  263. /* Need to expand SKB */
  264. if (unlikely(!cfpkt_pad_trail(pkt, len - skb->len)))
  265. PKT_ERROR(pkt, "cfpkt_setlen: skb_pad_trail failed\n");
  266. return cfpkt_getlen(pkt);
  267. }
  268. EXPORT_SYMBOL(cfpkt_setlen);
  269. struct cfpkt *cfpkt_create_uplink(const unsigned char *data, unsigned int len)
  270. {
  271. struct cfpkt *pkt = cfpkt_create_pfx(len + PKT_POSTFIX, PKT_PREFIX);
  272. if (!pkt)
  273. return NULL;
  274. if (unlikely(data != NULL))
  275. cfpkt_add_body(pkt, data, len);
  276. return pkt;
  277. }
  278. EXPORT_SYMBOL(cfpkt_create_uplink);
  279. struct cfpkt *cfpkt_append(struct cfpkt *dstpkt,
  280. struct cfpkt *addpkt,
  281. u16 expectlen)
  282. {
  283. struct sk_buff *dst = pkt_to_skb(dstpkt);
  284. struct sk_buff *add = pkt_to_skb(addpkt);
  285. u16 addlen = skb_headlen(add);
  286. u16 neededtailspace;
  287. struct sk_buff *tmp;
  288. u16 dstlen;
  289. u16 createlen;
  290. if (unlikely(is_erronous(dstpkt) || is_erronous(addpkt))) {
  291. return dstpkt;
  292. }
  293. if (expectlen > addlen)
  294. neededtailspace = expectlen;
  295. else
  296. neededtailspace = addlen;
  297. if (dst->tail + neededtailspace > dst->end) {
  298. /* Create a dumplicate of 'dst' with more tail space */
  299. struct cfpkt *tmppkt;
  300. dstlen = skb_headlen(dst);
  301. createlen = dstlen + neededtailspace;
  302. tmppkt = cfpkt_create(createlen + PKT_PREFIX + PKT_POSTFIX);
  303. if (tmppkt == NULL)
  304. return NULL;
  305. tmp = pkt_to_skb(tmppkt);
  306. skb_set_tail_pointer(tmp, dstlen);
  307. tmp->len = dstlen;
  308. memcpy(tmp->data, dst->data, dstlen);
  309. cfpkt_destroy(dstpkt);
  310. dst = tmp;
  311. }
  312. memcpy(skb_tail_pointer(dst), add->data, skb_headlen(add));
  313. cfpkt_destroy(addpkt);
  314. dst->tail += addlen;
  315. dst->len += addlen;
  316. return skb_to_pkt(dst);
  317. }
  318. EXPORT_SYMBOL(cfpkt_append);
  319. struct cfpkt *cfpkt_split(struct cfpkt *pkt, u16 pos)
  320. {
  321. struct sk_buff *skb2;
  322. struct sk_buff *skb = pkt_to_skb(pkt);
  323. struct cfpkt *tmppkt;
  324. u8 *split = skb->data + pos;
  325. u16 len2nd = skb_tail_pointer(skb) - split;
  326. if (unlikely(is_erronous(pkt)))
  327. return NULL;
  328. if (skb->data + pos > skb_tail_pointer(skb)) {
  329. PKT_ERROR(pkt,
  330. "cfpkt_split: trying to split beyond end of packet");
  331. return NULL;
  332. }
  333. /* Create a new packet for the second part of the data */
  334. tmppkt = cfpkt_create_pfx(len2nd + PKT_PREFIX + PKT_POSTFIX,
  335. PKT_PREFIX);
  336. if (tmppkt == NULL)
  337. return NULL;
  338. skb2 = pkt_to_skb(tmppkt);
  339. if (skb2 == NULL)
  340. return NULL;
  341. /* Reduce the length of the original packet */
  342. skb_set_tail_pointer(skb, pos);
  343. skb->len = pos;
  344. memcpy(skb2->data, split, len2nd);
  345. skb2->tail += len2nd;
  346. skb2->len += len2nd;
  347. return skb_to_pkt(skb2);
  348. }
  349. EXPORT_SYMBOL(cfpkt_split);
  350. char *cfpkt_log_pkt(struct cfpkt *pkt, char *buf, int buflen)
  351. {
  352. struct sk_buff *skb = pkt_to_skb(pkt);
  353. char *p = buf;
  354. int i;
  355. /*
  356. * Sanity check buffer length, it needs to be at least as large as
  357. * the header info: ~=50+ bytes
  358. */
  359. if (buflen < 50)
  360. return NULL;
  361. snprintf(buf, buflen, "%s: pkt:%p len:%ld(%ld+%ld) {%ld,%ld} data: [",
  362. is_erronous(pkt) ? "ERRONOUS-SKB" :
  363. (skb->data_len != 0 ? "COMPLEX-SKB" : "SKB"),
  364. skb,
  365. (long) skb->len,
  366. (long) (skb_tail_pointer(skb) - skb->data),
  367. (long) skb->data_len,
  368. (long) (skb->data - skb->head),
  369. (long) (skb_tail_pointer(skb) - skb->head));
  370. p = buf + strlen(buf);
  371. for (i = 0; i < skb_tail_pointer(skb) - skb->data && i < 300; i++) {
  372. if (p > buf + buflen - 10) {
  373. sprintf(p, "...");
  374. p = buf + strlen(buf);
  375. break;
  376. }
  377. sprintf(p, "%02x,", skb->data[i]);
  378. p = buf + strlen(buf);
  379. }
  380. sprintf(p, "]\n");
  381. return buf;
  382. }
  383. EXPORT_SYMBOL(cfpkt_log_pkt);
  384. int cfpkt_raw_append(struct cfpkt *pkt, void **buf, unsigned int buflen)
  385. {
  386. struct sk_buff *skb = pkt_to_skb(pkt);
  387. struct sk_buff *lastskb;
  388. caif_assert(buf != NULL);
  389. if (unlikely(is_erronous(pkt)))
  390. return -EPROTO;
  391. /* Make sure SKB is writable */
  392. if (unlikely(skb_cow_data(skb, 0, &lastskb) < 0)) {
  393. PKT_ERROR(pkt, "cfpkt_raw_append: skb_cow_data failed\n");
  394. return -EPROTO;
  395. }
  396. if (unlikely(skb_linearize(skb) != 0)) {
  397. PKT_ERROR(pkt, "cfpkt_raw_append: linearize failed\n");
  398. return -EPROTO;
  399. }
  400. if (unlikely(skb_tailroom(skb) < buflen)) {
  401. PKT_ERROR(pkt, "cfpkt_raw_append: buffer too short - failed\n");
  402. return -EPROTO;
  403. }
  404. *buf = skb_put(skb, buflen);
  405. return 1;
  406. }
  407. EXPORT_SYMBOL(cfpkt_raw_append);
  408. int cfpkt_raw_extract(struct cfpkt *pkt, void **buf, unsigned int buflen)
  409. {
  410. struct sk_buff *skb = pkt_to_skb(pkt);
  411. caif_assert(buf != NULL);
  412. if (unlikely(is_erronous(pkt)))
  413. return -EPROTO;
  414. if (unlikely(buflen > skb->len)) {
  415. PKT_ERROR(pkt, "cfpkt_raw_extract: buflen too large "
  416. "- failed\n");
  417. return -EPROTO;
  418. }
  419. if (unlikely(buflen > skb_headlen(skb))) {
  420. if (unlikely(skb_linearize(skb) != 0)) {
  421. PKT_ERROR(pkt, "cfpkt_raw_extract: linearize failed\n");
  422. return -EPROTO;
  423. }
  424. }
  425. *buf = skb->data;
  426. skb_pull(skb, buflen);
  427. return 1;
  428. }
  429. EXPORT_SYMBOL(cfpkt_raw_extract);
  430. inline bool cfpkt_erroneous(struct cfpkt *pkt)
  431. {
  432. return cfpkt_priv(pkt)->erronous;
  433. }
  434. EXPORT_SYMBOL(cfpkt_erroneous);
  435. struct cfpktq *cfpktq_create(void)
  436. {
  437. struct cfpktq *q = kmalloc(sizeof(struct cfpktq), GFP_ATOMIC);
  438. if (!q)
  439. return NULL;
  440. skb_queue_head_init(&q->head);
  441. atomic_set(&q->count, 0);
  442. spin_lock_init(&q->lock);
  443. return q;
  444. }
  445. EXPORT_SYMBOL(cfpktq_create);
  446. void cfpkt_queue(struct cfpktq *pktq, struct cfpkt *pkt, unsigned short prio)
  447. {
  448. atomic_inc(&pktq->count);
  449. spin_lock(&pktq->lock);
  450. skb_queue_tail(&pktq->head, pkt_to_skb(pkt));
  451. spin_unlock(&pktq->lock);
  452. }
  453. EXPORT_SYMBOL(cfpkt_queue);
  454. struct cfpkt *cfpkt_qpeek(struct cfpktq *pktq)
  455. {
  456. struct cfpkt *tmp;
  457. spin_lock(&pktq->lock);
  458. tmp = skb_to_pkt(skb_peek(&pktq->head));
  459. spin_unlock(&pktq->lock);
  460. return tmp;
  461. }
  462. EXPORT_SYMBOL(cfpkt_qpeek);
  463. struct cfpkt *cfpkt_dequeue(struct cfpktq *pktq)
  464. {
  465. struct cfpkt *pkt;
  466. spin_lock(&pktq->lock);
  467. pkt = skb_to_pkt(skb_dequeue(&pktq->head));
  468. if (pkt) {
  469. atomic_dec(&pktq->count);
  470. caif_assert(atomic_read(&pktq->count) >= 0);
  471. }
  472. spin_unlock(&pktq->lock);
  473. return pkt;
  474. }
  475. EXPORT_SYMBOL(cfpkt_dequeue);
  476. int cfpkt_qcount(struct cfpktq *pktq)
  477. {
  478. return atomic_read(&pktq->count);
  479. }
  480. EXPORT_SYMBOL(cfpkt_qcount);
  481. struct cfpkt *cfpkt_clone_release(struct cfpkt *pkt)
  482. {
  483. struct cfpkt *clone;
  484. clone = skb_to_pkt(skb_clone(pkt_to_skb(pkt), GFP_ATOMIC));
  485. /* Free original packet. */
  486. cfpkt_destroy(pkt);
  487. if (!clone)
  488. return NULL;
  489. return clone;
  490. }
  491. EXPORT_SYMBOL(cfpkt_clone_release);
  492. struct caif_payload_info *cfpkt_info(struct cfpkt *pkt)
  493. {
  494. return (struct caif_payload_info *)&pkt_to_skb(pkt)->cb;
  495. }
  496. EXPORT_SYMBOL(cfpkt_info);