From 6d13705e9331463e15d1d568ddd48c4f7aa1dbbb Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Mon, 4 Nov 2019 09:02:14 -0600 Subject: [PATCH] net/netlink: The NETLINK_ROUTE logic needs to return the first queued response and not attempt to match up reponses with requests. That is the Linux compatible way. Also, use queue.h functions for list management and fix an error in arp_snapshot(). --- net/arp/arp_table.c | 2 +- net/netlink/netlink.h | 13 ++++---- net/netlink/netlink_conn.c | 65 ++++++++++++------------------------- net/netlink/netlink_route.c | 5 ++- 4 files changed, 30 insertions(+), 55 deletions(-) diff --git a/net/arp/arp_table.c b/net/arp/arp_table.c index 030b686264..dea0c4e91f 100644 --- a/net/arp/arp_table.c +++ b/net/arp/arp_table.c @@ -429,7 +429,7 @@ unsigned int arp_snapshot(FAR struct arp_entry_s *snapshot, i++) { tabptr = &g_arptable[i]; - if (tabptr->at_ipaddr == 0 && + if (tabptr->at_ipaddr != 0 && now - tabptr->at_time <= ARP_MAXAGE_TICK) { memcpy(&snapshot[ncopied], tabptr, sizeof(struct arp_entry_s)); diff --git a/net/netlink/netlink.h b/net/netlink/netlink.h index 967c0f173d..4d9701ef87 100644 --- a/net/netlink/netlink.h +++ b/net/netlink/netlink.h @@ -72,7 +72,7 @@ struct netlink_response_s { - FAR struct netlink_response_s *flink; + sq_entry_t flink; FAR struct nlmsghdr msg; }; @@ -102,7 +102,7 @@ struct netlink_conn_s /* Buffered response data */ - FAR struct netlink_response_s *resplist; + sq_queue_t resplist; /* Singly linked list of responses*/ }; /**************************************************************************** @@ -186,7 +186,7 @@ FAR struct netlink_conn_s *netlink_active(FAR struct sockaddr_nl *addr); * Name: netlink_add_response * * Description: - * Add response data at the head of the pending response list. + * Add response data at the tail of the pending response list. * * Assumptions: * The caller has the network locked to prevent concurrent access to the @@ -201,8 +201,8 @@ void netlink_add_response(FAR struct socket *psock, * Name: netlink_get_response * * Description: - * Find the response matching the request. Remove it from the list of - * pending responses and return the response data. + * Return the next response from the head of the pending response list. + * Responses are returned one-at-a-time in FIFO order. * * Assumptions: * The caller has the network locked to prevent concurrent access to the @@ -210,8 +210,7 @@ void netlink_add_response(FAR struct socket *psock, * ****************************************************************************/ -FAR struct netlink_response_s * - netlink_get_response(FAR struct socket *psock, FAR struct nlmsghdr *nlmsg); +FAR struct netlink_response_s *netlink_get_response(FAR struct socket *psock); /**************************************************************************** * Name: netlink_route_sendto() diff --git a/net/netlink/netlink_conn.c b/net/netlink/netlink_conn.c index 3d4eee67d0..1e9aae169f 100644 --- a/net/netlink/netlink_conn.c +++ b/net/netlink/netlink_conn.c @@ -41,12 +41,14 @@ #include #include +#include #include #include #include #include +#include #include #include #include @@ -182,6 +184,8 @@ FAR struct netlink_conn_s *netlink_alloc(void) void netlink_free(FAR struct netlink_conn_s *conn) { + FAR sq_entry_t *resp; + /* The free list is protected by a semaphore (that behaves like a mutex). */ DEBUGASSERT(conn->crefs == 0); @@ -192,6 +196,13 @@ void netlink_free(FAR struct netlink_conn_s *conn) dq_rem(&conn->node, &g_active_netlink_connections); + /* Free any unclaimed responses */ + + while ((resp = sq_remfirst(&conn->resplist)) != NULL) + { + kmm_free(resp); + } + /* Reset structure */ memset(conn, 0, sizeof(*conn)); @@ -247,7 +258,7 @@ FAR struct netlink_conn_s *netlink_active(FAR struct sockaddr_nl *addr) * Name: netlink_add_response * * Description: - * Add response data at the head of the pending response list. + * Add response data at the tail of the pending response list. * * Assumptions: * The caller has the network locked to prevent concurrent access to the @@ -262,17 +273,16 @@ void netlink_add_response(FAR struct socket *psock, DEBUGASSERT(psock != NULL && psock->s_conn != NULL && resp != NULL); - conn = (FAR struct netlink_conn_s *)psock->s_conn; - resp->flink = conn->resplist; - conn->resplist = resp; + conn = (FAR struct netlink_conn_s *)psock->s_conn; + sq_addlast(&resp->flink, &conn->resplist); } /**************************************************************************** * Name: netlink_get_response * * Description: - * Find the response matching the request. Remove it from the list of - * pending responses and return the response data. + * Return the next response from the head of the pending response list. + * Responses are returned one-at-a-time in FIFO order. * * Assumptions: * The caller has the network locked to prevent concurrent access to the @@ -280,52 +290,19 @@ void netlink_add_response(FAR struct socket *psock, * ****************************************************************************/ -FAR struct netlink_response_s * - netlink_get_response(FAR struct socket *psock, FAR struct nlmsghdr *nlmsg) +FAR struct netlink_response_s *netlink_get_response(FAR struct socket *psock) { FAR struct netlink_conn_s *conn; - FAR struct netlink_response_s *curr; - FAR struct netlink_response_s *prev; - DEBUGASSERT(psock != NULL && psock->s_conn != NULL && nlmsg != NULL); + DEBUGASSERT(psock != NULL && psock->s_conn != NULL); conn = (FAR struct netlink_conn_s *)psock->s_conn; - /* Search the pending response data for this socket and find the entry - * with the matching sequence. Here is is assumed that the sequence - * number is unique and, hence, it is not necessary to verify other - * information. + /* Return the response at the head of the pending response list (may be + * NULL). */ - for (prev = NULL, curr = conn->resplist; - curr != NULL; - prev = curr, curr = curr->flink) - { - /* Check for a matching sequence number */ - - if (curr->msg.nlmsg_seq == nlmsg->nlmsg_seq) - { - /* We have a match */ - - DEBUGASSERT(curr->msg.nlmsg_type == nlmsg->nlmsg_type); - - /* Remove the entry from the list and return it */ - - if (prev != NULL) - { - prev->flink = curr->flink; - } - else - { - conn->resplist = curr->flink; - } - - curr->flink = NULL; - return curr; - } - } - - return NULL; + return (FAR struct netlink_response_s *)sq_remfirst(&conn->resplist); } #endif /* CONFIG_NET_NETLINK */ diff --git a/net/netlink/netlink_route.c b/net/netlink/netlink_route.c index 7dfa95ea49..630d9293ba 100644 --- a/net/netlink/netlink_route.c +++ b/net/netlink/netlink_route.c @@ -97,7 +97,7 @@ struct nlroute_recvfrom_response_s struct nlroute_recvfrom_rsplist_s { - FAR struct netlink_reqdata_s *flink; + sq_entry_t flink; struct nlroute_recvfrom_response_s payload; }; @@ -234,14 +234,13 @@ ssize_t netlink_route_recvfrom(FAR struct socket *psock, ssize_t ret; DEBUGASSERT(psock != NULL && nlmsg != NULL && - nlmsg->nlmsg_len >= sizeof(struct nlmsghdr) && len >= sizeof(struct nlmsghdr)); /* Find the response to this message */ net_lock(); entry = (FAR struct nlroute_recvfrom_rsplist_s *) - netlink_get_response(psock, nlmsg); + netlink_get_response(psock); net_unlock(); if (entry == NULL)