diff --git a/net/qrtr/af_qrtr.c b/net/qrtr/af_qrtr.c index cd16f774bbc7..27e3785c8596 100644 --- a/net/qrtr/af_qrtr.c +++ b/net/qrtr/af_qrtr.c @@ -471,6 +471,48 @@ static void qrtr_node_assign(struct qrtr_node *node, unsigned int nid) spin_unlock_irqrestore(&qrtr_nodes_lock, flags); } +/** + * qrtr_peek_pkt_size() - Peek into the packet header to get potential pkt size + * + * @data: Starting address of the packet which points to router header. + * + * @returns: potential packet size on success, < 0 on error. + * + * This function is used by the underlying transport abstraction layer to + * peek into the potential packet size of an incoming packet. This information + * is used to perform link layer fragmentation and re-assembly + */ +int qrtr_peek_pkt_size(const void *data) +{ + const struct qrtr_hdr_v1 *v1; + const struct qrtr_hdr_v2 *v2; + unsigned int hdrlen; + unsigned int size; + unsigned int ver; + + /* Version field in v1 is little endian, so this works for both cases */ + ver = *(u8 *)data; + + switch (ver) { + case QRTR_PROTO_VER_1: + v1 = data; + hdrlen = sizeof(*v1); + size = le32_to_cpu(v1->size); + break; + case QRTR_PROTO_VER_2: + v2 = data; + hdrlen = sizeof(*v2) + v2->optlen; + size = le32_to_cpu(v2->size); + break; + default: + pr_err("qrtr: Invalid version %d\n", ver); + return -EINVAL; + } + + return ALIGN(size, 4) + hdrlen; +} +EXPORT_SYMBOL(qrtr_peek_pkt_size); + /** * qrtr_endpoint_post() - post incoming data * @ep: endpoint handle diff --git a/net/qrtr/qrtr.h b/net/qrtr/qrtr.h index 3f2d28696062..2f7bd02b21ae 100644 --- a/net/qrtr/qrtr.h +++ b/net/qrtr/qrtr.h @@ -33,4 +33,5 @@ int qrtr_ns_init(void); void qrtr_ns_remove(void); +int qrtr_peek_pkt_size(const void *data); #endif