From 22e63b1f1bf689d3b19a0de2e5217aca3a2cfff9 Mon Sep 17 00:00:00 2001 From: Chris Lew Date: Tue, 11 Dec 2018 18:55:52 -0800 Subject: [PATCH] net: qrtr: Add support for DEL_PROC control message Add the DEL_PROC control message for forwarding usecases. If this proc acts as a gateway between two procs then they need a notification to clean up servers and client ports when either goes down. This message acts as notification to clean up all resources associated with the node in the message. Change-Id: I3514f54aa0221e104196e2120e929cc9f351847d Signed-off-by: Chris Lew --- include/uapi/linux/qrtr.h | 7 +++++ net/qrtr/qrtr.c | 57 +++++++++++++++++++++++++++++++++++++++ net/qrtr/qrtr.h | 2 ++ 3 files changed, 66 insertions(+) diff --git a/include/uapi/linux/qrtr.h b/include/uapi/linux/qrtr.h index f7e2fb3d752b..ad3b401f1e2e 100644 --- a/include/uapi/linux/qrtr.h +++ b/include/uapi/linux/qrtr.h @@ -27,6 +27,8 @@ enum qrtr_pkt_type { QRTR_TYPE_NEW_LOOKUP = 10, QRTR_TYPE_DEL_LOOKUP = 11, }; +#define QRTR_TYPE_DEL_PROC 13 + struct qrtr_ctrl_pkt { __le32 cmd; @@ -43,6 +45,11 @@ struct qrtr_ctrl_pkt { __le32 node; __le32 port; } client; + + struct { + __le32 rsvd; + __le32 node; + } proc; }; } __packed; diff --git a/net/qrtr/qrtr.c b/net/qrtr/qrtr.c index 4b39d0a70231..87d5f7523e6d 100644 --- a/net/qrtr/qrtr.c +++ b/net/qrtr/qrtr.c @@ -838,6 +838,60 @@ static void qrtr_notify_bye(u32 nid) qrtr_local_enqueue(NULL, skb, QRTR_TYPE_BYE, &src, &dst, 0); } +static u32 qrtr_calc_checksum(struct qrtr_ctrl_pkt *pkt) +{ + u32 checksum = 0; + u32 mask = 0xffff; + u16 upper_nb; + u16 lower_nb; + u32 *msg; + int i; + + if (!pkt) + return checksum; + msg = (u32 *)pkt; + + for (i = 0; i < sizeof(*pkt) / sizeof(*msg); i++) { + lower_nb = *msg & mask; + upper_nb = (*msg >> 16) & mask; + checksum += (upper_nb + lower_nb); + msg++; + } + while (checksum > 0xffff) + checksum = (checksum & mask) + ((checksum >> 16) & mask); + + checksum = ~checksum & mask; + + return checksum; +} + +static void qrtr_fwd_del_proc(struct qrtr_node *src, unsigned int nid) +{ + struct sockaddr_qrtr from = {AF_QIPCRTR, 0, QRTR_PORT_CTRL}; + struct sockaddr_qrtr to = {AF_QIPCRTR, 0, QRTR_PORT_CTRL}; + struct qrtr_ctrl_pkt *pkt; + struct qrtr_node *dst; + struct sk_buff *skb; + + list_for_each_entry(dst, &qrtr_all_epts, item) { + if (!qrtr_must_forward(src, dst, QRTR_TYPE_DEL_PROC)) + continue; + + skb = qrtr_alloc_ctrl_packet(&pkt); + if (!skb) + return; + + pkt->cmd = cpu_to_le32(QRTR_TYPE_DEL_PROC); + pkt->proc.rsvd = QRTR_DEL_PROC_MAGIC; + pkt->proc.node = cpu_to_le32(nid); + pkt->proc.rsvd = cpu_to_le32(qrtr_calc_checksum(pkt)); + + from.sq_node = src->nid; + to.sq_node = dst->nid; + qrtr_node_enqueue(dst, skb, QRTR_TYPE_DEL_PROC, &from, &to, 0); + } +} + /** * qrtr_endpoint_unregister - unregister endpoint * @ep: endpoint to unregister @@ -861,7 +915,10 @@ void qrtr_endpoint_unregister(struct qrtr_endpoint *ep) continue; spin_unlock_irqrestore(&qrtr_nodes_lock, flags); + qrtr_notify_bye(iter.index); + qrtr_fwd_del_proc(node, iter.index); + spin_lock_irqsave(&qrtr_nodes_lock, flags); } spin_unlock_irqrestore(&qrtr_nodes_lock, flags); diff --git a/net/qrtr/qrtr.h b/net/qrtr/qrtr.h index fc6dcb368419..b80a14918c87 100644 --- a/net/qrtr/qrtr.h +++ b/net/qrtr/qrtr.h @@ -10,6 +10,8 @@ struct sk_buff; #define QRTR_EP_NID_AUTO (-1) #define QRTR_EP_NET_ID_AUTO (1) +#define QRTR_DEL_PROC_MAGIC 0xe111 + /** * struct qrtr_endpoint - endpoint handle * @xmit: Callback for outgoing packets