diff options
Diffstat (limited to 'net/caif/cfpkt_skbuff.c')
-rw-r--r-- | net/caif/cfpkt_skbuff.c | 178 |
1 files changed, 5 insertions, 173 deletions
diff --git a/net/caif/cfpkt_skbuff.c b/net/caif/cfpkt_skbuff.c index d7e865e2ff65..20c6cb3522e0 100644 --- a/net/caif/cfpkt_skbuff.c +++ b/net/caif/cfpkt_skbuff.c | |||
@@ -42,22 +42,22 @@ struct cfpkt_priv_data { | |||
42 | bool erronous; | 42 | bool erronous; |
43 | }; | 43 | }; |
44 | 44 | ||
45 | inline struct cfpkt_priv_data *cfpkt_priv(struct cfpkt *pkt) | 45 | static inline struct cfpkt_priv_data *cfpkt_priv(struct cfpkt *pkt) |
46 | { | 46 | { |
47 | return (struct cfpkt_priv_data *) pkt->skb.cb; | 47 | return (struct cfpkt_priv_data *) pkt->skb.cb; |
48 | } | 48 | } |
49 | 49 | ||
50 | inline bool is_erronous(struct cfpkt *pkt) | 50 | static inline bool is_erronous(struct cfpkt *pkt) |
51 | { | 51 | { |
52 | return cfpkt_priv(pkt)->erronous; | 52 | return cfpkt_priv(pkt)->erronous; |
53 | } | 53 | } |
54 | 54 | ||
55 | inline struct sk_buff *pkt_to_skb(struct cfpkt *pkt) | 55 | static inline struct sk_buff *pkt_to_skb(struct cfpkt *pkt) |
56 | { | 56 | { |
57 | return &pkt->skb; | 57 | return &pkt->skb; |
58 | } | 58 | } |
59 | 59 | ||
60 | inline struct cfpkt *skb_to_pkt(struct sk_buff *skb) | 60 | static inline struct cfpkt *skb_to_pkt(struct sk_buff *skb) |
61 | { | 61 | { |
62 | return (struct cfpkt *) skb; | 62 | return (struct cfpkt *) skb; |
63 | } | 63 | } |
@@ -317,17 +317,6 @@ int cfpkt_setlen(struct cfpkt *pkt, u16 len) | |||
317 | } | 317 | } |
318 | EXPORT_SYMBOL(cfpkt_setlen); | 318 | EXPORT_SYMBOL(cfpkt_setlen); |
319 | 319 | ||
320 | struct cfpkt *cfpkt_create_uplink(const unsigned char *data, unsigned int len) | ||
321 | { | ||
322 | struct cfpkt *pkt = cfpkt_create_pfx(len + PKT_POSTFIX, PKT_PREFIX); | ||
323 | if (!pkt) | ||
324 | return NULL; | ||
325 | if (unlikely(data != NULL)) | ||
326 | cfpkt_add_body(pkt, data, len); | ||
327 | return pkt; | ||
328 | } | ||
329 | EXPORT_SYMBOL(cfpkt_create_uplink); | ||
330 | |||
331 | struct cfpkt *cfpkt_append(struct cfpkt *dstpkt, | 320 | struct cfpkt *cfpkt_append(struct cfpkt *dstpkt, |
332 | struct cfpkt *addpkt, | 321 | struct cfpkt *addpkt, |
333 | u16 expectlen) | 322 | u16 expectlen) |
@@ -408,169 +397,12 @@ struct cfpkt *cfpkt_split(struct cfpkt *pkt, u16 pos) | |||
408 | } | 397 | } |
409 | EXPORT_SYMBOL(cfpkt_split); | 398 | EXPORT_SYMBOL(cfpkt_split); |
410 | 399 | ||
411 | char *cfpkt_log_pkt(struct cfpkt *pkt, char *buf, int buflen) | 400 | bool cfpkt_erroneous(struct cfpkt *pkt) |
412 | { | ||
413 | struct sk_buff *skb = pkt_to_skb(pkt); | ||
414 | char *p = buf; | ||
415 | int i; | ||
416 | |||
417 | /* | ||
418 | * Sanity check buffer length, it needs to be at least as large as | ||
419 | * the header info: ~=50+ bytes | ||
420 | */ | ||
421 | if (buflen < 50) | ||
422 | return NULL; | ||
423 | |||
424 | snprintf(buf, buflen, "%s: pkt:%p len:%ld(%ld+%ld) {%ld,%ld} data: [", | ||
425 | is_erronous(pkt) ? "ERRONOUS-SKB" : | ||
426 | (skb->data_len != 0 ? "COMPLEX-SKB" : "SKB"), | ||
427 | skb, | ||
428 | (long) skb->len, | ||
429 | (long) (skb_tail_pointer(skb) - skb->data), | ||
430 | (long) skb->data_len, | ||
431 | (long) (skb->data - skb->head), | ||
432 | (long) (skb_tail_pointer(skb) - skb->head)); | ||
433 | p = buf + strlen(buf); | ||
434 | |||
435 | for (i = 0; i < skb_tail_pointer(skb) - skb->data && i < 300; i++) { | ||
436 | if (p > buf + buflen - 10) { | ||
437 | sprintf(p, "..."); | ||
438 | p = buf + strlen(buf); | ||
439 | break; | ||
440 | } | ||
441 | sprintf(p, "%02x,", skb->data[i]); | ||
442 | p = buf + strlen(buf); | ||
443 | } | ||
444 | sprintf(p, "]\n"); | ||
445 | return buf; | ||
446 | } | ||
447 | EXPORT_SYMBOL(cfpkt_log_pkt); | ||
448 | |||
449 | int cfpkt_raw_append(struct cfpkt *pkt, void **buf, unsigned int buflen) | ||
450 | { | ||
451 | struct sk_buff *skb = pkt_to_skb(pkt); | ||
452 | struct sk_buff *lastskb; | ||
453 | |||
454 | caif_assert(buf != NULL); | ||
455 | if (unlikely(is_erronous(pkt))) | ||
456 | return -EPROTO; | ||
457 | /* Make sure SKB is writable */ | ||
458 | if (unlikely(skb_cow_data(skb, 0, &lastskb) < 0)) { | ||
459 | PKT_ERROR(pkt, "skb_cow_data failed\n"); | ||
460 | return -EPROTO; | ||
461 | } | ||
462 | |||
463 | if (unlikely(skb_linearize(skb) != 0)) { | ||
464 | PKT_ERROR(pkt, "linearize failed\n"); | ||
465 | return -EPROTO; | ||
466 | } | ||
467 | |||
468 | if (unlikely(skb_tailroom(skb) < buflen)) { | ||
469 | PKT_ERROR(pkt, "buffer too short - failed\n"); | ||
470 | return -EPROTO; | ||
471 | } | ||
472 | |||
473 | *buf = skb_put(skb, buflen); | ||
474 | return 1; | ||
475 | } | ||
476 | EXPORT_SYMBOL(cfpkt_raw_append); | ||
477 | |||
478 | int cfpkt_raw_extract(struct cfpkt *pkt, void **buf, unsigned int buflen) | ||
479 | { | ||
480 | struct sk_buff *skb = pkt_to_skb(pkt); | ||
481 | |||
482 | caif_assert(buf != NULL); | ||
483 | if (unlikely(is_erronous(pkt))) | ||
484 | return -EPROTO; | ||
485 | |||
486 | if (unlikely(buflen > skb->len)) { | ||
487 | PKT_ERROR(pkt, "buflen too large - failed\n"); | ||
488 | return -EPROTO; | ||
489 | } | ||
490 | |||
491 | if (unlikely(buflen > skb_headlen(skb))) { | ||
492 | if (unlikely(skb_linearize(skb) != 0)) { | ||
493 | PKT_ERROR(pkt, "linearize failed\n"); | ||
494 | return -EPROTO; | ||
495 | } | ||
496 | } | ||
497 | |||
498 | *buf = skb->data; | ||
499 | skb_pull(skb, buflen); | ||
500 | |||
501 | return 1; | ||
502 | } | ||
503 | EXPORT_SYMBOL(cfpkt_raw_extract); | ||
504 | |||
505 | inline bool cfpkt_erroneous(struct cfpkt *pkt) | ||
506 | { | 401 | { |
507 | return cfpkt_priv(pkt)->erronous; | 402 | return cfpkt_priv(pkt)->erronous; |
508 | } | 403 | } |
509 | EXPORT_SYMBOL(cfpkt_erroneous); | 404 | EXPORT_SYMBOL(cfpkt_erroneous); |
510 | 405 | ||
511 | struct cfpktq *cfpktq_create(void) | ||
512 | { | ||
513 | struct cfpktq *q = kmalloc(sizeof(struct cfpktq), GFP_ATOMIC); | ||
514 | if (!q) | ||
515 | return NULL; | ||
516 | skb_queue_head_init(&q->head); | ||
517 | atomic_set(&q->count, 0); | ||
518 | spin_lock_init(&q->lock); | ||
519 | return q; | ||
520 | } | ||
521 | EXPORT_SYMBOL(cfpktq_create); | ||
522 | |||
523 | void cfpkt_queue(struct cfpktq *pktq, struct cfpkt *pkt, unsigned short prio) | ||
524 | { | ||
525 | atomic_inc(&pktq->count); | ||
526 | spin_lock(&pktq->lock); | ||
527 | skb_queue_tail(&pktq->head, pkt_to_skb(pkt)); | ||
528 | spin_unlock(&pktq->lock); | ||
529 | |||
530 | } | ||
531 | EXPORT_SYMBOL(cfpkt_queue); | ||
532 | |||
533 | struct cfpkt *cfpkt_qpeek(struct cfpktq *pktq) | ||
534 | { | ||
535 | struct cfpkt *tmp; | ||
536 | spin_lock(&pktq->lock); | ||
537 | tmp = skb_to_pkt(skb_peek(&pktq->head)); | ||
538 | spin_unlock(&pktq->lock); | ||
539 | return tmp; | ||
540 | } | ||
541 | EXPORT_SYMBOL(cfpkt_qpeek); | ||
542 | |||
543 | struct cfpkt *cfpkt_dequeue(struct cfpktq *pktq) | ||
544 | { | ||
545 | struct cfpkt *pkt; | ||
546 | spin_lock(&pktq->lock); | ||
547 | pkt = skb_to_pkt(skb_dequeue(&pktq->head)); | ||
548 | if (pkt) { | ||
549 | atomic_dec(&pktq->count); | ||
550 | caif_assert(atomic_read(&pktq->count) >= 0); | ||
551 | } | ||
552 | spin_unlock(&pktq->lock); | ||
553 | return pkt; | ||
554 | } | ||
555 | EXPORT_SYMBOL(cfpkt_dequeue); | ||
556 | |||
557 | int cfpkt_qcount(struct cfpktq *pktq) | ||
558 | { | ||
559 | return atomic_read(&pktq->count); | ||
560 | } | ||
561 | EXPORT_SYMBOL(cfpkt_qcount); | ||
562 | |||
563 | struct cfpkt *cfpkt_clone_release(struct cfpkt *pkt) | ||
564 | { | ||
565 | struct cfpkt *clone; | ||
566 | clone = skb_to_pkt(skb_clone(pkt_to_skb(pkt), GFP_ATOMIC)); | ||
567 | /* Free original packet. */ | ||
568 | cfpkt_destroy(pkt); | ||
569 | if (!clone) | ||
570 | return NULL; | ||
571 | return clone; | ||
572 | } | ||
573 | EXPORT_SYMBOL(cfpkt_clone_release); | ||
574 | 406 | ||
575 | struct caif_payload_info *cfpkt_info(struct cfpkt *pkt) | 407 | struct caif_payload_info *cfpkt_info(struct cfpkt *pkt) |
576 | { | 408 | { |