Merge branch 'net-qrtr-add-distant-node-support'
Loic Poulain says: ==================== net: qrtr: Add distant node support QRTR protocol allows a node to communicate with an other non-immediate node via an intermdediate immediate node acting as a 'bridge': node-0 <=> node-1 <=> node-2 This is currently not supported in this upstream version and this series aim to fix that. This series is V2 because changes 1, 2 and 3 have already been submitted separately on LKML. Changes in v2: - Add reviewed-by tags from Bjorn and Mani - Fixing checkpatch issue reported by Jakub ==================== Link: https://lore.kernel.org/r/1604684010-24090-1-git-send-email-loic.poulain@linaro.org Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Коммит
c079fe2480
|
@ -517,10 +517,6 @@ static int ctrl_cmd_new_server(struct sockaddr_qrtr *from,
|
|||
port = from->sq_port;
|
||||
}
|
||||
|
||||
/* Don't accept spoofed messages */
|
||||
if (from->sq_node != node_id)
|
||||
return -EINVAL;
|
||||
|
||||
srv = server_add(service, instance, node_id, port);
|
||||
if (!srv)
|
||||
return -EINVAL;
|
||||
|
@ -559,10 +555,6 @@ static int ctrl_cmd_del_server(struct sockaddr_qrtr *from,
|
|||
port = from->sq_port;
|
||||
}
|
||||
|
||||
/* Don't accept spoofed messages */
|
||||
if (from->sq_node != node_id)
|
||||
return -EINVAL;
|
||||
|
||||
/* Local servers may only unregister themselves */
|
||||
if (from->sq_node == qrtr_ns.local_node && from->sq_port != port)
|
||||
return -EINVAL;
|
||||
|
|
|
@ -171,8 +171,13 @@ static void __qrtr_node_release(struct kref *kref)
|
|||
void __rcu **slot;
|
||||
|
||||
spin_lock_irqsave(&qrtr_nodes_lock, flags);
|
||||
if (node->nid != QRTR_EP_NID_AUTO)
|
||||
radix_tree_delete(&qrtr_nodes, node->nid);
|
||||
/* If the node is a bridge for other nodes, there are possibly
|
||||
* multiple entries pointing to our released node, delete them all.
|
||||
*/
|
||||
radix_tree_for_each_slot(slot, &qrtr_nodes, &iter, 0) {
|
||||
if (*slot == node)
|
||||
radix_tree_iter_delete(&qrtr_nodes, &iter, slot);
|
||||
}
|
||||
spin_unlock_irqrestore(&qrtr_nodes_lock, flags);
|
||||
|
||||
list_del(&node->item);
|
||||
|
@ -347,7 +352,7 @@ static int qrtr_node_enqueue(struct qrtr_node *node, struct sk_buff *skb,
|
|||
hdr->src_port_id = cpu_to_le32(from->sq_port);
|
||||
if (to->sq_port == QRTR_PORT_CTRL) {
|
||||
hdr->dst_node_id = cpu_to_le32(node->nid);
|
||||
hdr->dst_port_id = cpu_to_le32(QRTR_NODE_BCAST);
|
||||
hdr->dst_port_id = cpu_to_le32(QRTR_PORT_CTRL);
|
||||
} else {
|
||||
hdr->dst_node_id = cpu_to_le32(to->sq_node);
|
||||
hdr->dst_port_id = cpu_to_le32(to->sq_port);
|
||||
|
@ -401,12 +406,13 @@ static void qrtr_node_assign(struct qrtr_node *node, unsigned int nid)
|
|||
{
|
||||
unsigned long flags;
|
||||
|
||||
if (node->nid != QRTR_EP_NID_AUTO || nid == QRTR_EP_NID_AUTO)
|
||||
if (nid == QRTR_EP_NID_AUTO)
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&qrtr_nodes_lock, flags);
|
||||
radix_tree_insert(&qrtr_nodes, nid, node);
|
||||
node->nid = nid;
|
||||
if (node->nid == QRTR_EP_NID_AUTO)
|
||||
node->nid = nid;
|
||||
spin_unlock_irqrestore(&qrtr_nodes_lock, flags);
|
||||
}
|
||||
|
||||
|
@ -494,6 +500,13 @@ int qrtr_endpoint_post(struct qrtr_endpoint *ep, const void *data, size_t len)
|
|||
|
||||
qrtr_node_assign(node, cb->src_node);
|
||||
|
||||
if (cb->type == QRTR_TYPE_NEW_SERVER) {
|
||||
/* Remote node endpoint can bridge other distant nodes */
|
||||
const struct qrtr_ctrl_pkt *pkt = data + hdrlen;
|
||||
|
||||
qrtr_node_assign(node, le32_to_cpu(pkt->server.node));
|
||||
}
|
||||
|
||||
if (cb->type == QRTR_TYPE_RESUME_TX) {
|
||||
qrtr_tx_resume(node, skb);
|
||||
} else {
|
||||
|
@ -519,18 +532,20 @@ EXPORT_SYMBOL_GPL(qrtr_endpoint_post);
|
|||
/**
|
||||
* qrtr_alloc_ctrl_packet() - allocate control packet skb
|
||||
* @pkt: reference to qrtr_ctrl_pkt pointer
|
||||
* @flags: the type of memory to allocate
|
||||
*
|
||||
* Returns newly allocated sk_buff, or NULL on failure
|
||||
*
|
||||
* This function allocates a sk_buff large enough to carry a qrtr_ctrl_pkt and
|
||||
* on success returns a reference to the control packet in @pkt.
|
||||
*/
|
||||
static struct sk_buff *qrtr_alloc_ctrl_packet(struct qrtr_ctrl_pkt **pkt)
|
||||
static struct sk_buff *qrtr_alloc_ctrl_packet(struct qrtr_ctrl_pkt **pkt,
|
||||
gfp_t flags)
|
||||
{
|
||||
const int pkt_len = sizeof(struct qrtr_ctrl_pkt);
|
||||
struct sk_buff *skb;
|
||||
|
||||
skb = alloc_skb(QRTR_HDR_MAX_SIZE + pkt_len, GFP_KERNEL);
|
||||
skb = alloc_skb(QRTR_HDR_MAX_SIZE + pkt_len, flags);
|
||||
if (!skb)
|
||||
return NULL;
|
||||
|
||||
|
@ -592,6 +607,7 @@ void qrtr_endpoint_unregister(struct qrtr_endpoint *ep)
|
|||
struct qrtr_ctrl_pkt *pkt;
|
||||
struct qrtr_tx_flow *flow;
|
||||
struct sk_buff *skb;
|
||||
unsigned long flags;
|
||||
void __rcu **slot;
|
||||
|
||||
mutex_lock(&node->ep_lock);
|
||||
|
@ -599,11 +615,18 @@ void qrtr_endpoint_unregister(struct qrtr_endpoint *ep)
|
|||
mutex_unlock(&node->ep_lock);
|
||||
|
||||
/* Notify the local controller about the event */
|
||||
skb = qrtr_alloc_ctrl_packet(&pkt);
|
||||
if (skb) {
|
||||
pkt->cmd = cpu_to_le32(QRTR_TYPE_BYE);
|
||||
qrtr_local_enqueue(NULL, skb, QRTR_TYPE_BYE, &src, &dst);
|
||||
spin_lock_irqsave(&qrtr_nodes_lock, flags);
|
||||
radix_tree_for_each_slot(slot, &qrtr_nodes, &iter, 0) {
|
||||
if (*slot != node)
|
||||
continue;
|
||||
src.sq_node = iter.index;
|
||||
skb = qrtr_alloc_ctrl_packet(&pkt, GFP_ATOMIC);
|
||||
if (skb) {
|
||||
pkt->cmd = cpu_to_le32(QRTR_TYPE_BYE);
|
||||
qrtr_local_enqueue(NULL, skb, QRTR_TYPE_BYE, &src, &dst);
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore(&qrtr_nodes_lock, flags);
|
||||
|
||||
/* Wake up any transmitters waiting for resume-tx from the node */
|
||||
mutex_lock(&node->qrtr_tx_lock);
|
||||
|
@ -656,7 +679,7 @@ static void qrtr_port_remove(struct qrtr_sock *ipc)
|
|||
to.sq_node = QRTR_NODE_BCAST;
|
||||
to.sq_port = QRTR_PORT_CTRL;
|
||||
|
||||
skb = qrtr_alloc_ctrl_packet(&pkt);
|
||||
skb = qrtr_alloc_ctrl_packet(&pkt, GFP_KERNEL);
|
||||
if (skb) {
|
||||
pkt->cmd = cpu_to_le32(QRTR_TYPE_DEL_CLIENT);
|
||||
pkt->client.node = cpu_to_le32(ipc->us.sq_node);
|
||||
|
@ -982,7 +1005,7 @@ static int qrtr_send_resume_tx(struct qrtr_cb *cb)
|
|||
if (!node)
|
||||
return -EINVAL;
|
||||
|
||||
skb = qrtr_alloc_ctrl_packet(&pkt);
|
||||
skb = qrtr_alloc_ctrl_packet(&pkt, GFP_KERNEL);
|
||||
if (!skb)
|
||||
return -ENOMEM;
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче