net: qrtr: Attempt to linearize skb for forwarding

The current QRTR transport feature set does not support fragmented skbs
which is a problem for packets that are forwarded from the rx path.

In order to linearize the skb, skb_put_padto() and skb_linearize() try
to allocate enough memory with GFP_ATOMIC but are prone to failure.

Pre-allocate enough headroom with GFP_KERNEL on forwarded packets. If
there are still problems with allocation, then continue and drop the
packet in qrtr_node_enqueue().

Change-Id: I7de6620bba26746698237d913ce064ea5725f921
Signed-off-by: Chris Lew <clew@codeaurora.org>
tirimbino
Chris Lew 5 years ago
parent 870f0ba0fc
commit 7f745d0379
  1. 20
      net/qrtr/qrtr.c

@ -819,6 +819,24 @@ static struct sk_buff *qrtr_alloc_ctrl_packet(struct qrtr_ctrl_pkt **pkt)
static struct qrtr_sock *qrtr_port_lookup(int port);
static void qrtr_port_put(struct qrtr_sock *ipc);
/* Prepare skb for forwarding by allocating enough linear memory to align and
* add the header since qrtr transports do not support fragmented skbs
*/
static void qrtr_skb_align_linearize(struct sk_buff *skb)
{
int nhead = ALIGN(skb->len, 4) + sizeof(struct qrtr_hdr_v1);
int rc;
if (!skb_is_nonlinear(skb))
return;
rc = pskb_expand_head(skb, nhead, 0, GFP_KERNEL);
skb_condense(skb);
if (rc)
pr_err("%s: failed:%d to allocate linear skb size:%d\n",
__func__, rc, nhead);
}
static bool qrtr_must_forward(struct qrtr_node *src,
struct qrtr_node *dst, u32 type)
{
@ -849,6 +867,7 @@ static void qrtr_fwd_ctrl_pkt(struct sk_buff *skb)
struct qrtr_node *src;
struct qrtr_cb *cb = (struct qrtr_cb *)skb->cb;
qrtr_skb_align_linearize(skb);
src = qrtr_node_lookup(cb->src_node);
down_read(&qrtr_node_lock);
list_for_each_entry(node, &qrtr_all_epts, item) {
@ -883,6 +902,7 @@ static void qrtr_fwd_pkt(struct sk_buff *skb, struct qrtr_cb *cb)
struct sockaddr_qrtr to = {AF_QIPCRTR, cb->dst_node, cb->dst_port};
struct qrtr_node *node;
qrtr_skb_align_linearize(skb);
node = qrtr_node_lookup(cb->dst_node);
if (!node) {
kfree_skb(skb);

Loading…
Cancel
Save