greybus: operation: rate-limit dev_err printing on the receive path
authorEli Sennesh <esennesh@leaflabs.com>
Fri, 13 May 2016 17:27:40 +0000 (13:27 -0400)
committerGreg Kroah-Hartman <gregkh@google.com>
Tue, 17 May 2016 16:21:10 +0000 (09:21 -0700)
When we receive Greybus operations we don't recognize, requests or responses,
en masse, we can pile up a lot of dev_err() printk messages.  Doing so along
the gb_connection_recv() code path can delay receive processing by up to seven
milliseconds, starving the system of bulk-IN urbs.  Rate limit those printk
messages, ensuring that after too many repeated errors at the same place in
the code-path, we'll stop printing to the console at all and let the urbs get
returned.

This will help prevent denial-of-service attacks on the AP through the UniPro
network from malicious or malfunctioning modules.

Testing Done: 7 msec recv-to-resubmit-urb processing times go down to <20
usecs

Signed-off-by: Eli Sennesh <esennesh@leaflabs.com>
Reviewed-by: Johan Hovold <johan@hovoldconsulting.com>
Reviewed-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
Reviewed-by: Mitchell Tasman <tasman@leaflabs.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
drivers/staging/greybus/operation.c

index 716627e..31df413 100644 (file)
@@ -891,7 +891,7 @@ static void gb_connection_recv_response(struct gb_connection *connection,
        size_t message_size;
 
        if (!operation_id) {
-               dev_err(&connection->hd->dev,
+               dev_err_ratelimited(&connection->hd->dev,
                                "%s: invalid response id 0 received\n",
                                connection->name);
                return;
@@ -899,9 +899,9 @@ static void gb_connection_recv_response(struct gb_connection *connection,
 
        operation = gb_operation_find_outgoing(connection, operation_id);
        if (!operation) {
-               dev_err(&connection->hd->dev,
-                       "%s: unexpected response id 0x%04x received\n",
-                       connection->name, operation_id);
+               dev_err_ratelimited(&connection->hd->dev,
+                               "%s: unexpected response id 0x%04x received\n",
+                               connection->name, operation_id);
                return;
        }
 
@@ -909,7 +909,7 @@ static void gb_connection_recv_response(struct gb_connection *connection,
        header = message->header;
        message_size = sizeof(*header) + message->payload_size;
        if (!errno && size > message_size) {
-               dev_err(&connection->hd->dev,
+               dev_err_ratelimited(&connection->hd->dev,
                                "%s: malformed response 0x%02x received (%zu > %zu)\n",
                                connection->name, header->type,
                                size, message_size);
@@ -918,7 +918,7 @@ static void gb_connection_recv_response(struct gb_connection *connection,
                if (gb_operation_short_response_allowed(operation)) {
                        message->payload_size = size - sizeof(*header);
                } else {
-                       dev_err(&connection->hd->dev,
+                       dev_err_ratelimited(&connection->hd->dev,
                                        "%s: short response 0x%02x received (%zu < %zu)\n",
                                        connection->name, header->type,
                                        size, message_size);
@@ -956,13 +956,14 @@ void gb_connection_recv(struct gb_connection *connection,
        if ((connection->state != GB_CONNECTION_STATE_ENABLED &&
                        connection->state != GB_CONNECTION_STATE_ENABLED_TX) ||
                        gb_connection_is_offloaded(connection)) {
-               dev_warn(dev, "%s: dropping %zu received bytes\n",
+               dev_warn_ratelimited(dev, "%s: dropping %zu received bytes\n",
                                connection->name, size);
                return;
        }
 
        if (size < sizeof(header)) {
-               dev_err(dev, "%s: short message received\n", connection->name);
+               dev_err_ratelimited(dev, "%s: short message received\n",
+                               connection->name);
                return;
        }
 
@@ -970,10 +971,11 @@ void gb_connection_recv(struct gb_connection *connection,
        memcpy(&header, data, sizeof(header));
        msg_size = le16_to_cpu(header.size);
        if (size < msg_size) {
-               dev_err(dev,
-                       "%s: incomplete message 0x%04x of type 0x%02x received (%zu < %zu)\n",
-                       connection->name, le16_to_cpu(header.operation_id),
-                       header.type, size, msg_size);
+               dev_err_ratelimited(dev,
+                               "%s: incomplete message 0x%04x of type 0x%02x received (%zu < %zu)\n",
+                               connection->name,
+                               le16_to_cpu(header.operation_id),
+                               header.type, size, msg_size);
                return;         /* XXX Should still complete operation */
        }