162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (C) ST-Ericsson AB 2010 462306a36Sopenharmony_ci * Author: Sjur Brendeland 562306a36Sopenharmony_ci */ 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ":%s(): " fmt, __func__ 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#include <linux/string.h> 1062306a36Sopenharmony_ci#include <linux/skbuff.h> 1162306a36Sopenharmony_ci#include <linux/export.h> 1262306a36Sopenharmony_ci#include <net/caif/cfpkt.h> 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci#define PKT_PREFIX 48 1562306a36Sopenharmony_ci#define PKT_POSTFIX 2 1662306a36Sopenharmony_ci#define PKT_LEN_WHEN_EXTENDING 128 1762306a36Sopenharmony_ci#define PKT_ERROR(pkt, errmsg) \ 1862306a36Sopenharmony_cido { \ 1962306a36Sopenharmony_ci cfpkt_priv(pkt)->erronous = true; \ 2062306a36Sopenharmony_ci skb_reset_tail_pointer(&pkt->skb); \ 2162306a36Sopenharmony_ci pr_warn(errmsg); \ 2262306a36Sopenharmony_ci} while (0) 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_cistruct cfpktq { 2562306a36Sopenharmony_ci struct sk_buff_head head; 2662306a36Sopenharmony_ci atomic_t count; 2762306a36Sopenharmony_ci /* Lock protects count updates */ 2862306a36Sopenharmony_ci spinlock_t lock; 2962306a36Sopenharmony_ci}; 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci/* 3262306a36Sopenharmony_ci * net/caif/ is generic and does not 3362306a36Sopenharmony_ci * understand SKB, so we do this typecast 3462306a36Sopenharmony_ci */ 3562306a36Sopenharmony_cistruct cfpkt { 3662306a36Sopenharmony_ci struct sk_buff skb; 3762306a36Sopenharmony_ci}; 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci/* Private data inside SKB */ 4062306a36Sopenharmony_cistruct cfpkt_priv_data { 4162306a36Sopenharmony_ci struct dev_info dev_info; 4262306a36Sopenharmony_ci bool erronous; 4362306a36Sopenharmony_ci}; 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_cistatic inline struct cfpkt_priv_data *cfpkt_priv(struct cfpkt *pkt) 4662306a36Sopenharmony_ci{ 4762306a36Sopenharmony_ci return (struct cfpkt_priv_data *) pkt->skb.cb; 4862306a36Sopenharmony_ci} 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_cistatic inline bool is_erronous(struct cfpkt *pkt) 5162306a36Sopenharmony_ci{ 5262306a36Sopenharmony_ci return cfpkt_priv(pkt)->erronous; 5362306a36Sopenharmony_ci} 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_cistatic inline struct sk_buff *pkt_to_skb(struct cfpkt *pkt) 5662306a36Sopenharmony_ci{ 5762306a36Sopenharmony_ci return &pkt->skb; 5862306a36Sopenharmony_ci} 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_cistatic inline struct cfpkt *skb_to_pkt(struct sk_buff *skb) 6162306a36Sopenharmony_ci{ 6262306a36Sopenharmony_ci return (struct cfpkt *) skb; 6362306a36Sopenharmony_ci} 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_cistruct cfpkt *cfpkt_fromnative(enum caif_direction dir, void *nativepkt) 6662306a36Sopenharmony_ci{ 6762306a36Sopenharmony_ci struct cfpkt *pkt = skb_to_pkt(nativepkt); 6862306a36Sopenharmony_ci cfpkt_priv(pkt)->erronous = false; 6962306a36Sopenharmony_ci return pkt; 7062306a36Sopenharmony_ci} 7162306a36Sopenharmony_ciEXPORT_SYMBOL(cfpkt_fromnative); 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_civoid *cfpkt_tonative(struct cfpkt *pkt) 7462306a36Sopenharmony_ci{ 7562306a36Sopenharmony_ci return (void *) pkt; 7662306a36Sopenharmony_ci} 7762306a36Sopenharmony_ciEXPORT_SYMBOL(cfpkt_tonative); 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_cistatic struct cfpkt *cfpkt_create_pfx(u16 len, u16 pfx) 8062306a36Sopenharmony_ci{ 8162306a36Sopenharmony_ci struct sk_buff *skb; 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ci skb = alloc_skb(len + pfx, GFP_ATOMIC); 8462306a36Sopenharmony_ci if (unlikely(skb == NULL)) 8562306a36Sopenharmony_ci return NULL; 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci skb_reserve(skb, pfx); 8862306a36Sopenharmony_ci return skb_to_pkt(skb); 8962306a36Sopenharmony_ci} 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ciinline struct cfpkt *cfpkt_create(u16 len) 9262306a36Sopenharmony_ci{ 9362306a36Sopenharmony_ci return cfpkt_create_pfx(len + PKT_POSTFIX, PKT_PREFIX); 9462306a36Sopenharmony_ci} 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_civoid cfpkt_destroy(struct cfpkt *pkt) 9762306a36Sopenharmony_ci{ 9862306a36Sopenharmony_ci struct sk_buff *skb = pkt_to_skb(pkt); 9962306a36Sopenharmony_ci kfree_skb(skb); 10062306a36Sopenharmony_ci} 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_ciinline bool cfpkt_more(struct cfpkt *pkt) 10362306a36Sopenharmony_ci{ 10462306a36Sopenharmony_ci struct sk_buff *skb = pkt_to_skb(pkt); 10562306a36Sopenharmony_ci return skb->len > 0; 10662306a36Sopenharmony_ci} 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ciint cfpkt_peek_head(struct cfpkt *pkt, void *data, u16 len) 10962306a36Sopenharmony_ci{ 11062306a36Sopenharmony_ci struct sk_buff *skb = pkt_to_skb(pkt); 11162306a36Sopenharmony_ci if (skb_headlen(skb) >= len) { 11262306a36Sopenharmony_ci memcpy(data, skb->data, len); 11362306a36Sopenharmony_ci return 0; 11462306a36Sopenharmony_ci } 11562306a36Sopenharmony_ci return !cfpkt_extr_head(pkt, data, len) && 11662306a36Sopenharmony_ci !cfpkt_add_head(pkt, data, len); 11762306a36Sopenharmony_ci} 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ciint cfpkt_extr_head(struct cfpkt *pkt, void *data, u16 len) 12062306a36Sopenharmony_ci{ 12162306a36Sopenharmony_ci struct sk_buff *skb = pkt_to_skb(pkt); 12262306a36Sopenharmony_ci u8 *from; 12362306a36Sopenharmony_ci if (unlikely(is_erronous(pkt))) 12462306a36Sopenharmony_ci return -EPROTO; 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_ci if (unlikely(len > skb->len)) { 12762306a36Sopenharmony_ci PKT_ERROR(pkt, "read beyond end of packet\n"); 12862306a36Sopenharmony_ci return -EPROTO; 12962306a36Sopenharmony_ci } 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci if (unlikely(len > skb_headlen(skb))) { 13262306a36Sopenharmony_ci if (unlikely(skb_linearize(skb) != 0)) { 13362306a36Sopenharmony_ci PKT_ERROR(pkt, "linearize failed\n"); 13462306a36Sopenharmony_ci return -EPROTO; 13562306a36Sopenharmony_ci } 13662306a36Sopenharmony_ci } 13762306a36Sopenharmony_ci from = skb_pull(skb, len); 13862306a36Sopenharmony_ci from -= len; 13962306a36Sopenharmony_ci if (data) 14062306a36Sopenharmony_ci memcpy(data, from, len); 14162306a36Sopenharmony_ci return 0; 14262306a36Sopenharmony_ci} 14362306a36Sopenharmony_ciEXPORT_SYMBOL(cfpkt_extr_head); 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_ciint cfpkt_extr_trail(struct cfpkt *pkt, void *dta, u16 len) 14662306a36Sopenharmony_ci{ 14762306a36Sopenharmony_ci struct sk_buff *skb = pkt_to_skb(pkt); 14862306a36Sopenharmony_ci u8 *data = dta; 14962306a36Sopenharmony_ci u8 *from; 15062306a36Sopenharmony_ci if (unlikely(is_erronous(pkt))) 15162306a36Sopenharmony_ci return -EPROTO; 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci if (unlikely(skb_linearize(skb) != 0)) { 15462306a36Sopenharmony_ci PKT_ERROR(pkt, "linearize failed\n"); 15562306a36Sopenharmony_ci return -EPROTO; 15662306a36Sopenharmony_ci } 15762306a36Sopenharmony_ci if (unlikely(skb->data + len > skb_tail_pointer(skb))) { 15862306a36Sopenharmony_ci PKT_ERROR(pkt, "read beyond end of packet\n"); 15962306a36Sopenharmony_ci return -EPROTO; 16062306a36Sopenharmony_ci } 16162306a36Sopenharmony_ci from = skb_tail_pointer(skb) - len; 16262306a36Sopenharmony_ci skb_trim(skb, skb->len - len); 16362306a36Sopenharmony_ci memcpy(data, from, len); 16462306a36Sopenharmony_ci return 0; 16562306a36Sopenharmony_ci} 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ciint cfpkt_pad_trail(struct cfpkt *pkt, u16 len) 16862306a36Sopenharmony_ci{ 16962306a36Sopenharmony_ci return cfpkt_add_body(pkt, NULL, len); 17062306a36Sopenharmony_ci} 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_ciint cfpkt_add_body(struct cfpkt *pkt, const void *data, u16 len) 17362306a36Sopenharmony_ci{ 17462306a36Sopenharmony_ci struct sk_buff *skb = pkt_to_skb(pkt); 17562306a36Sopenharmony_ci struct sk_buff *lastskb; 17662306a36Sopenharmony_ci u8 *to; 17762306a36Sopenharmony_ci u16 addlen = 0; 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ci if (unlikely(is_erronous(pkt))) 18162306a36Sopenharmony_ci return -EPROTO; 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_ci lastskb = skb; 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ci /* Check whether we need to add space at the tail */ 18662306a36Sopenharmony_ci if (unlikely(skb_tailroom(skb) < len)) { 18762306a36Sopenharmony_ci if (likely(len < PKT_LEN_WHEN_EXTENDING)) 18862306a36Sopenharmony_ci addlen = PKT_LEN_WHEN_EXTENDING; 18962306a36Sopenharmony_ci else 19062306a36Sopenharmony_ci addlen = len; 19162306a36Sopenharmony_ci } 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci /* Check whether we need to change the SKB before writing to the tail */ 19462306a36Sopenharmony_ci if (unlikely((addlen > 0) || skb_cloned(skb) || skb_shared(skb))) { 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_ci /* Make sure data is writable */ 19762306a36Sopenharmony_ci if (unlikely(skb_cow_data(skb, addlen, &lastskb) < 0)) { 19862306a36Sopenharmony_ci PKT_ERROR(pkt, "cow failed\n"); 19962306a36Sopenharmony_ci return -EPROTO; 20062306a36Sopenharmony_ci } 20162306a36Sopenharmony_ci } 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ci /* All set to put the last SKB and optionally write data there. */ 20462306a36Sopenharmony_ci to = pskb_put(skb, lastskb, len); 20562306a36Sopenharmony_ci if (likely(data)) 20662306a36Sopenharmony_ci memcpy(to, data, len); 20762306a36Sopenharmony_ci return 0; 20862306a36Sopenharmony_ci} 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_ciinline int cfpkt_addbdy(struct cfpkt *pkt, u8 data) 21162306a36Sopenharmony_ci{ 21262306a36Sopenharmony_ci return cfpkt_add_body(pkt, &data, 1); 21362306a36Sopenharmony_ci} 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_ciint cfpkt_add_head(struct cfpkt *pkt, const void *data2, u16 len) 21662306a36Sopenharmony_ci{ 21762306a36Sopenharmony_ci struct sk_buff *skb = pkt_to_skb(pkt); 21862306a36Sopenharmony_ci struct sk_buff *lastskb; 21962306a36Sopenharmony_ci u8 *to; 22062306a36Sopenharmony_ci const u8 *data = data2; 22162306a36Sopenharmony_ci int ret; 22262306a36Sopenharmony_ci if (unlikely(is_erronous(pkt))) 22362306a36Sopenharmony_ci return -EPROTO; 22462306a36Sopenharmony_ci if (unlikely(skb_headroom(skb) < len)) { 22562306a36Sopenharmony_ci PKT_ERROR(pkt, "no headroom\n"); 22662306a36Sopenharmony_ci return -EPROTO; 22762306a36Sopenharmony_ci } 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_ci /* Make sure data is writable */ 23062306a36Sopenharmony_ci ret = skb_cow_data(skb, 0, &lastskb); 23162306a36Sopenharmony_ci if (unlikely(ret < 0)) { 23262306a36Sopenharmony_ci PKT_ERROR(pkt, "cow failed\n"); 23362306a36Sopenharmony_ci return ret; 23462306a36Sopenharmony_ci } 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_ci to = skb_push(skb, len); 23762306a36Sopenharmony_ci memcpy(to, data, len); 23862306a36Sopenharmony_ci return 0; 23962306a36Sopenharmony_ci} 24062306a36Sopenharmony_ciEXPORT_SYMBOL(cfpkt_add_head); 24162306a36Sopenharmony_ci 24262306a36Sopenharmony_ciinline int cfpkt_add_trail(struct cfpkt *pkt, const void *data, u16 len) 24362306a36Sopenharmony_ci{ 24462306a36Sopenharmony_ci return cfpkt_add_body(pkt, data, len); 24562306a36Sopenharmony_ci} 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_ciinline u16 cfpkt_getlen(struct cfpkt *pkt) 24862306a36Sopenharmony_ci{ 24962306a36Sopenharmony_ci struct sk_buff *skb = pkt_to_skb(pkt); 25062306a36Sopenharmony_ci return skb->len; 25162306a36Sopenharmony_ci} 25262306a36Sopenharmony_ci 25362306a36Sopenharmony_ciint cfpkt_iterate(struct cfpkt *pkt, 25462306a36Sopenharmony_ci u16 (*iter_func)(u16, void *, u16), 25562306a36Sopenharmony_ci u16 data) 25662306a36Sopenharmony_ci{ 25762306a36Sopenharmony_ci /* 25862306a36Sopenharmony_ci * Don't care about the performance hit of linearizing, 25962306a36Sopenharmony_ci * Checksum should not be used on high-speed interfaces anyway. 26062306a36Sopenharmony_ci */ 26162306a36Sopenharmony_ci if (unlikely(is_erronous(pkt))) 26262306a36Sopenharmony_ci return -EPROTO; 26362306a36Sopenharmony_ci if (unlikely(skb_linearize(&pkt->skb) != 0)) { 26462306a36Sopenharmony_ci PKT_ERROR(pkt, "linearize failed\n"); 26562306a36Sopenharmony_ci return -EPROTO; 26662306a36Sopenharmony_ci } 26762306a36Sopenharmony_ci return iter_func(data, pkt->skb.data, cfpkt_getlen(pkt)); 26862306a36Sopenharmony_ci} 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_ciint cfpkt_setlen(struct cfpkt *pkt, u16 len) 27162306a36Sopenharmony_ci{ 27262306a36Sopenharmony_ci struct sk_buff *skb = pkt_to_skb(pkt); 27362306a36Sopenharmony_ci 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ci if (unlikely(is_erronous(pkt))) 27662306a36Sopenharmony_ci return -EPROTO; 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_ci if (likely(len <= skb->len)) { 27962306a36Sopenharmony_ci if (unlikely(skb->data_len)) 28062306a36Sopenharmony_ci ___pskb_trim(skb, len); 28162306a36Sopenharmony_ci else 28262306a36Sopenharmony_ci skb_trim(skb, len); 28362306a36Sopenharmony_ci 28462306a36Sopenharmony_ci return cfpkt_getlen(pkt); 28562306a36Sopenharmony_ci } 28662306a36Sopenharmony_ci 28762306a36Sopenharmony_ci /* Need to expand SKB */ 28862306a36Sopenharmony_ci if (unlikely(!cfpkt_pad_trail(pkt, len - skb->len))) 28962306a36Sopenharmony_ci PKT_ERROR(pkt, "skb_pad_trail failed\n"); 29062306a36Sopenharmony_ci 29162306a36Sopenharmony_ci return cfpkt_getlen(pkt); 29262306a36Sopenharmony_ci} 29362306a36Sopenharmony_ci 29462306a36Sopenharmony_cistruct cfpkt *cfpkt_append(struct cfpkt *dstpkt, 29562306a36Sopenharmony_ci struct cfpkt *addpkt, 29662306a36Sopenharmony_ci u16 expectlen) 29762306a36Sopenharmony_ci{ 29862306a36Sopenharmony_ci struct sk_buff *dst = pkt_to_skb(dstpkt); 29962306a36Sopenharmony_ci struct sk_buff *add = pkt_to_skb(addpkt); 30062306a36Sopenharmony_ci u16 addlen = skb_headlen(add); 30162306a36Sopenharmony_ci u16 neededtailspace; 30262306a36Sopenharmony_ci struct sk_buff *tmp; 30362306a36Sopenharmony_ci u16 dstlen; 30462306a36Sopenharmony_ci u16 createlen; 30562306a36Sopenharmony_ci if (unlikely(is_erronous(dstpkt) || is_erronous(addpkt))) { 30662306a36Sopenharmony_ci return dstpkt; 30762306a36Sopenharmony_ci } 30862306a36Sopenharmony_ci if (expectlen > addlen) 30962306a36Sopenharmony_ci neededtailspace = expectlen; 31062306a36Sopenharmony_ci else 31162306a36Sopenharmony_ci neededtailspace = addlen; 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_ci if (dst->tail + neededtailspace > dst->end) { 31462306a36Sopenharmony_ci /* Create a dumplicate of 'dst' with more tail space */ 31562306a36Sopenharmony_ci struct cfpkt *tmppkt; 31662306a36Sopenharmony_ci dstlen = skb_headlen(dst); 31762306a36Sopenharmony_ci createlen = dstlen + neededtailspace; 31862306a36Sopenharmony_ci tmppkt = cfpkt_create(createlen + PKT_PREFIX + PKT_POSTFIX); 31962306a36Sopenharmony_ci if (tmppkt == NULL) 32062306a36Sopenharmony_ci return NULL; 32162306a36Sopenharmony_ci tmp = pkt_to_skb(tmppkt); 32262306a36Sopenharmony_ci skb_put_data(tmp, dst->data, dstlen); 32362306a36Sopenharmony_ci cfpkt_destroy(dstpkt); 32462306a36Sopenharmony_ci dst = tmp; 32562306a36Sopenharmony_ci } 32662306a36Sopenharmony_ci skb_put_data(dst, add->data, skb_headlen(add)); 32762306a36Sopenharmony_ci cfpkt_destroy(addpkt); 32862306a36Sopenharmony_ci return skb_to_pkt(dst); 32962306a36Sopenharmony_ci} 33062306a36Sopenharmony_ci 33162306a36Sopenharmony_cistruct cfpkt *cfpkt_split(struct cfpkt *pkt, u16 pos) 33262306a36Sopenharmony_ci{ 33362306a36Sopenharmony_ci struct sk_buff *skb2; 33462306a36Sopenharmony_ci struct sk_buff *skb = pkt_to_skb(pkt); 33562306a36Sopenharmony_ci struct cfpkt *tmppkt; 33662306a36Sopenharmony_ci u8 *split = skb->data + pos; 33762306a36Sopenharmony_ci u16 len2nd = skb_tail_pointer(skb) - split; 33862306a36Sopenharmony_ci 33962306a36Sopenharmony_ci if (unlikely(is_erronous(pkt))) 34062306a36Sopenharmony_ci return NULL; 34162306a36Sopenharmony_ci 34262306a36Sopenharmony_ci if (skb->data + pos > skb_tail_pointer(skb)) { 34362306a36Sopenharmony_ci PKT_ERROR(pkt, "trying to split beyond end of packet\n"); 34462306a36Sopenharmony_ci return NULL; 34562306a36Sopenharmony_ci } 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_ci /* Create a new packet for the second part of the data */ 34862306a36Sopenharmony_ci tmppkt = cfpkt_create_pfx(len2nd + PKT_PREFIX + PKT_POSTFIX, 34962306a36Sopenharmony_ci PKT_PREFIX); 35062306a36Sopenharmony_ci if (tmppkt == NULL) 35162306a36Sopenharmony_ci return NULL; 35262306a36Sopenharmony_ci skb2 = pkt_to_skb(tmppkt); 35362306a36Sopenharmony_ci 35462306a36Sopenharmony_ci 35562306a36Sopenharmony_ci if (skb2 == NULL) 35662306a36Sopenharmony_ci return NULL; 35762306a36Sopenharmony_ci 35862306a36Sopenharmony_ci skb_put_data(skb2, split, len2nd); 35962306a36Sopenharmony_ci 36062306a36Sopenharmony_ci /* Reduce the length of the original packet */ 36162306a36Sopenharmony_ci skb_trim(skb, pos); 36262306a36Sopenharmony_ci 36362306a36Sopenharmony_ci skb2->priority = skb->priority; 36462306a36Sopenharmony_ci return skb_to_pkt(skb2); 36562306a36Sopenharmony_ci} 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_cibool cfpkt_erroneous(struct cfpkt *pkt) 36862306a36Sopenharmony_ci{ 36962306a36Sopenharmony_ci return cfpkt_priv(pkt)->erronous; 37062306a36Sopenharmony_ci} 37162306a36Sopenharmony_ci 37262306a36Sopenharmony_cistruct caif_payload_info *cfpkt_info(struct cfpkt *pkt) 37362306a36Sopenharmony_ci{ 37462306a36Sopenharmony_ci return (struct caif_payload_info *)&pkt_to_skb(pkt)->cb; 37562306a36Sopenharmony_ci} 37662306a36Sopenharmony_ciEXPORT_SYMBOL(cfpkt_info); 37762306a36Sopenharmony_ci 37862306a36Sopenharmony_civoid cfpkt_set_prio(struct cfpkt *pkt, int prio) 37962306a36Sopenharmony_ci{ 38062306a36Sopenharmony_ci pkt_to_skb(pkt)->priority = prio; 38162306a36Sopenharmony_ci} 38262306a36Sopenharmony_ciEXPORT_SYMBOL(cfpkt_set_prio); 383