Skip to content

Commit e704448

Browse files
anderssondavem330
authored andcommitted
net: qrtr: Pass source and destination to enqueue functions
Defer writing the message header to the skb until its time to enqueue the packet. As the receive path is reworked to decode the message header as it's received from the transport and only pass around the payload in the skb this change means that we do not have to fill out the full message header just to decode it immediately in qrtr_local_enqueue(). In the future this change also makes it possible to prepend message headers based on the version of each link. Signed-off-by: Bjorn Andersson <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent da7653f commit e704448

File tree

1 file changed

+69
-51
lines changed

1 file changed

+69
-51
lines changed

net/qrtr/qrtr.c

Lines changed: 69 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,12 @@ struct qrtr_node {
9797
struct list_head item;
9898
};
9999

100-
static int qrtr_local_enqueue(struct qrtr_node *node, struct sk_buff *skb);
101-
static int qrtr_bcast_enqueue(struct qrtr_node *node, struct sk_buff *skb);
100+
static int qrtr_local_enqueue(struct qrtr_node *node, struct sk_buff *skb,
101+
int type, struct sockaddr_qrtr *from,
102+
struct sockaddr_qrtr *to);
103+
static int qrtr_bcast_enqueue(struct qrtr_node *node, struct sk_buff *skb,
104+
int type, struct sockaddr_qrtr *from,
105+
struct sockaddr_qrtr *to);
102106

103107
/* Release node resources and free the node.
104108
*
@@ -136,10 +140,27 @@ static void qrtr_node_release(struct qrtr_node *node)
136140
}
137141

138142
/* Pass an outgoing packet socket buffer to the endpoint driver. */
139-
static int qrtr_node_enqueue(struct qrtr_node *node, struct sk_buff *skb)
143+
static int qrtr_node_enqueue(struct qrtr_node *node, struct sk_buff *skb,
144+
int type, struct sockaddr_qrtr *from,
145+
struct sockaddr_qrtr *to)
140146
{
147+
struct qrtr_hdr *hdr;
148+
size_t len = skb->len;
141149
int rc = -ENODEV;
142150

151+
hdr = skb_push(skb, QRTR_HDR_SIZE);
152+
hdr->version = cpu_to_le32(QRTR_PROTO_VER);
153+
hdr->type = cpu_to_le32(type);
154+
hdr->src_node_id = cpu_to_le32(from->sq_node);
155+
hdr->src_port_id = cpu_to_le32(from->sq_port);
156+
hdr->dst_node_id = cpu_to_le32(to->sq_node);
157+
hdr->dst_port_id = cpu_to_le32(to->sq_port);
158+
159+
hdr->size = cpu_to_le32(len);
160+
hdr->confirm_rx = 0;
161+
162+
skb_put_padto(skb, ALIGN(len, 4));
163+
143164
mutex_lock(&node->ep_lock);
144165
if (node->ep)
145166
rc = node->ep->xmit(node->ep, skb);
@@ -237,23 +258,13 @@ EXPORT_SYMBOL_GPL(qrtr_endpoint_post);
237258
static struct sk_buff *qrtr_alloc_ctrl_packet(u32 type, size_t pkt_len,
238259
u32 src_node, u32 dst_node)
239260
{
240-
struct qrtr_hdr *hdr;
241261
struct sk_buff *skb;
242262

243263
skb = alloc_skb(QRTR_HDR_SIZE + pkt_len, GFP_KERNEL);
244264
if (!skb)
245265
return NULL;
246-
skb_reset_transport_header(skb);
247266

248-
hdr = skb_put(skb, QRTR_HDR_SIZE);
249-
hdr->version = cpu_to_le32(QRTR_PROTO_VER);
250-
hdr->type = cpu_to_le32(type);
251-
hdr->src_node_id = cpu_to_le32(src_node);
252-
hdr->src_port_id = cpu_to_le32(QRTR_PORT_CTRL);
253-
hdr->confirm_rx = cpu_to_le32(0);
254-
hdr->size = cpu_to_le32(pkt_len);
255-
hdr->dst_node_id = cpu_to_le32(dst_node);
256-
hdr->dst_port_id = cpu_to_le32(QRTR_PORT_CTRL);
267+
skb_reserve(skb, QRTR_HDR_SIZE);
257268

258269
return skb;
259270
}
@@ -326,6 +337,8 @@ static void qrtr_port_put(struct qrtr_sock *ipc);
326337
static void qrtr_node_rx_work(struct work_struct *work)
327338
{
328339
struct qrtr_node *node = container_of(work, struct qrtr_node, work);
340+
struct sockaddr_qrtr dst;
341+
struct sockaddr_qrtr src;
329342
struct sk_buff *skb;
330343

331344
while ((skb = skb_dequeue(&node->rx_queue)) != NULL) {
@@ -341,6 +354,11 @@ static void qrtr_node_rx_work(struct work_struct *work)
341354
dst_port = le32_to_cpu(phdr->dst_port_id);
342355
confirm = !!phdr->confirm_rx;
343356

357+
src.sq_node = src_node;
358+
src.sq_port = le32_to_cpu(phdr->src_port_id);
359+
dst.sq_node = dst_node;
360+
dst.sq_port = dst_port;
361+
344362
qrtr_node_assign(node, src_node);
345363

346364
ipc = qrtr_port_lookup(dst_port);
@@ -357,7 +375,9 @@ static void qrtr_node_rx_work(struct work_struct *work)
357375
skb = qrtr_alloc_resume_tx(dst_node, node->nid, dst_port);
358376
if (!skb)
359377
break;
360-
if (qrtr_node_enqueue(node, skb))
378+
379+
if (qrtr_node_enqueue(node, skb, QRTR_TYPE_RESUME_TX,
380+
&dst, &src))
361381
break;
362382
}
363383
}
@@ -407,6 +427,8 @@ EXPORT_SYMBOL_GPL(qrtr_endpoint_register);
407427
void qrtr_endpoint_unregister(struct qrtr_endpoint *ep)
408428
{
409429
struct qrtr_node *node = ep->node;
430+
struct sockaddr_qrtr src = {AF_QIPCRTR, node->nid, QRTR_PORT_CTRL};
431+
struct sockaddr_qrtr dst = {AF_QIPCRTR, qrtr_local_nid, QRTR_PORT_CTRL};
410432
struct sk_buff *skb;
411433

412434
mutex_lock(&node->ep_lock);
@@ -416,7 +438,7 @@ void qrtr_endpoint_unregister(struct qrtr_endpoint *ep)
416438
/* Notify the local controller about the event */
417439
skb = qrtr_alloc_local_bye(node->nid);
418440
if (skb)
419-
qrtr_local_enqueue(NULL, skb);
441+
qrtr_local_enqueue(NULL, skb, QRTR_TYPE_BYE, &src, &dst);
420442

421443
qrtr_node_release(node);
422444
ep->node = NULL;
@@ -454,11 +476,17 @@ static void qrtr_port_remove(struct qrtr_sock *ipc)
454476
{
455477
struct sk_buff *skb;
456478
int port = ipc->us.sq_port;
479+
struct sockaddr_qrtr to;
480+
481+
to.sq_family = AF_QIPCRTR;
482+
to.sq_node = QRTR_NODE_BCAST;
483+
to.sq_port = QRTR_PORT_CTRL;
457484

458485
skb = qrtr_alloc_del_client(&ipc->us);
459486
if (skb) {
460487
skb_set_owner_w(skb, &ipc->sk);
461-
qrtr_bcast_enqueue(NULL, skb);
488+
qrtr_bcast_enqueue(NULL, skb, QRTR_TYPE_DEL_CLIENT, &ipc->us,
489+
&to);
462490
}
463491

464492
if (port == QRTR_PORT_CTRL)
@@ -606,19 +634,25 @@ static int qrtr_bind(struct socket *sock, struct sockaddr *saddr, int len)
606634
}
607635

608636
/* Queue packet to local peer socket. */
609-
static int qrtr_local_enqueue(struct qrtr_node *node, struct sk_buff *skb)
637+
static int qrtr_local_enqueue(struct qrtr_node *node, struct sk_buff *skb,
638+
int type, struct sockaddr_qrtr *from,
639+
struct sockaddr_qrtr *to)
610640
{
611-
const struct qrtr_hdr *phdr;
612641
struct qrtr_sock *ipc;
642+
struct qrtr_hdr *phdr;
613643

614-
phdr = (const struct qrtr_hdr *)skb_transport_header(skb);
615-
616-
ipc = qrtr_port_lookup(le32_to_cpu(phdr->dst_port_id));
644+
ipc = qrtr_port_lookup(to->sq_port);
617645
if (!ipc || &ipc->sk == skb->sk) { /* do not send to self */
618646
kfree_skb(skb);
619647
return -ENODEV;
620648
}
621649

650+
phdr = skb_push(skb, QRTR_HDR_SIZE);
651+
skb_reset_transport_header(skb);
652+
653+
phdr->src_node_id = cpu_to_le32(from->sq_node);
654+
phdr->src_port_id = cpu_to_le32(from->sq_port);
655+
622656
if (sock_queue_rcv_skb(&ipc->sk, skb)) {
623657
qrtr_port_put(ipc);
624658
kfree_skb(skb);
@@ -631,7 +665,9 @@ static int qrtr_local_enqueue(struct qrtr_node *node, struct sk_buff *skb)
631665
}
632666

633667
/* Queue packet for broadcast. */
634-
static int qrtr_bcast_enqueue(struct qrtr_node *node, struct sk_buff *skb)
668+
static int qrtr_bcast_enqueue(struct qrtr_node *node, struct sk_buff *skb,
669+
int type, struct sockaddr_qrtr *from,
670+
struct sockaddr_qrtr *to)
635671
{
636672
struct sk_buff *skbn;
637673

@@ -641,25 +677,26 @@ static int qrtr_bcast_enqueue(struct qrtr_node *node, struct sk_buff *skb)
641677
if (!skbn)
642678
break;
643679
skb_set_owner_w(skbn, skb->sk);
644-
qrtr_node_enqueue(node, skbn);
680+
qrtr_node_enqueue(node, skbn, type, from, to);
645681
}
646682
mutex_unlock(&qrtr_node_lock);
647683

648-
qrtr_local_enqueue(node, skb);
684+
qrtr_local_enqueue(node, skb, type, from, to);
649685

650686
return 0;
651687
}
652688

653689
static int qrtr_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
654690
{
655691
DECLARE_SOCKADDR(struct sockaddr_qrtr *, addr, msg->msg_name);
656-
int (*enqueue_fn)(struct qrtr_node *, struct sk_buff *);
692+
int (*enqueue_fn)(struct qrtr_node *, struct sk_buff *, int,
693+
struct sockaddr_qrtr *, struct sockaddr_qrtr *);
657694
struct qrtr_sock *ipc = qrtr_sk(sock->sk);
658695
struct sock *sk = sock->sk;
659696
struct qrtr_node *node;
660-
struct qrtr_hdr *hdr;
661697
struct sk_buff *skb;
662698
size_t plen;
699+
u32 type = QRTR_TYPE_DATA;
663700
int rc;
664701

665702
if (msg->msg_flags & ~(MSG_DONTWAIT))
@@ -713,32 +750,14 @@ static int qrtr_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
713750
if (!skb)
714751
goto out_node;
715752

716-
skb_reset_transport_header(skb);
717-
skb_put(skb, len + QRTR_HDR_SIZE);
718-
719-
hdr = (struct qrtr_hdr *)skb_transport_header(skb);
720-
hdr->version = cpu_to_le32(QRTR_PROTO_VER);
721-
hdr->src_node_id = cpu_to_le32(ipc->us.sq_node);
722-
hdr->src_port_id = cpu_to_le32(ipc->us.sq_port);
723-
hdr->confirm_rx = cpu_to_le32(0);
724-
hdr->size = cpu_to_le32(len);
725-
hdr->dst_node_id = cpu_to_le32(addr->sq_node);
726-
hdr->dst_port_id = cpu_to_le32(addr->sq_port);
753+
skb_reserve(skb, QRTR_HDR_SIZE);
727754

728-
rc = skb_copy_datagram_from_iter(skb, QRTR_HDR_SIZE,
729-
&msg->msg_iter, len);
755+
rc = memcpy_from_msg(skb_put(skb, len), msg, len);
730756
if (rc) {
731757
kfree_skb(skb);
732758
goto out_node;
733759
}
734760

735-
if (plen != len) {
736-
rc = skb_pad(skb, plen - len);
737-
if (rc)
738-
goto out_node;
739-
skb_put(skb, plen - len);
740-
}
741-
742761
if (ipc->us.sq_port == QRTR_PORT_CTRL) {
743762
if (len < 4) {
744763
rc = -EINVAL;
@@ -747,12 +766,11 @@ static int qrtr_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
747766
}
748767

749768
/* control messages already require the type as 'command' */
750-
skb_copy_bits(skb, QRTR_HDR_SIZE, &hdr->type, 4);
751-
} else {
752-
hdr->type = cpu_to_le32(QRTR_TYPE_DATA);
769+
skb_copy_bits(skb, 0, &type, 4);
770+
type = le32_to_cpu(type);
753771
}
754772

755-
rc = enqueue_fn(node, skb);
773+
rc = enqueue_fn(node, skb, type, &ipc->us, addr);
756774
if (rc >= 0)
757775
rc = len;
758776

0 commit comments

Comments
 (0)