devlink: report 0 after hitting end in region read
[linux-2.6-microblaze.git] / net / core / devlink.c
index f76219b..549ee56 100644 (file)
@@ -3986,6 +3986,12 @@ static int devlink_nl_cmd_region_read_dumpit(struct sk_buff *skb,
                goto out_unlock;
        }
 
+       /* return 0 if there is no further data to read */
+       if (start_offset >= region->size) {
+               err = 0;
+               goto out_unlock;
+       }
+
        hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq,
                          &devlink_nl_family, NLM_F_ACK | NLM_F_MULTI,
                          DEVLINK_CMD_REGION_READ);
@@ -4843,22 +4849,100 @@ devlink_health_reporter_destroy(struct devlink_health_reporter *reporter)
 }
 EXPORT_SYMBOL_GPL(devlink_health_reporter_destroy);
 
-void
-devlink_health_reporter_state_update(struct devlink_health_reporter *reporter,
-                                    enum devlink_health_reporter_state state)
+static int
+devlink_nl_health_reporter_fill(struct sk_buff *msg,
+                               struct devlink *devlink,
+                               struct devlink_health_reporter *reporter,
+                               enum devlink_command cmd, u32 portid,
+                               u32 seq, int flags)
 {
-       if (WARN_ON(state != DEVLINK_HEALTH_REPORTER_STATE_HEALTHY &&
-                   state != DEVLINK_HEALTH_REPORTER_STATE_ERROR))
+       struct nlattr *reporter_attr;
+       void *hdr;
+
+       hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
+       if (!hdr)
+               return -EMSGSIZE;
+
+       if (devlink_nl_put_handle(msg, devlink))
+               goto genlmsg_cancel;
+
+       reporter_attr = nla_nest_start_noflag(msg,
+                                             DEVLINK_ATTR_HEALTH_REPORTER);
+       if (!reporter_attr)
+               goto genlmsg_cancel;
+       if (nla_put_string(msg, DEVLINK_ATTR_HEALTH_REPORTER_NAME,
+                          reporter->ops->name))
+               goto reporter_nest_cancel;
+       if (nla_put_u8(msg, DEVLINK_ATTR_HEALTH_REPORTER_STATE,
+                      reporter->health_state))
+               goto reporter_nest_cancel;
+       if (nla_put_u64_64bit(msg, DEVLINK_ATTR_HEALTH_REPORTER_ERR_COUNT,
+                             reporter->error_count, DEVLINK_ATTR_PAD))
+               goto reporter_nest_cancel;
+       if (nla_put_u64_64bit(msg, DEVLINK_ATTR_HEALTH_REPORTER_RECOVER_COUNT,
+                             reporter->recovery_count, DEVLINK_ATTR_PAD))
+               goto reporter_nest_cancel;
+       if (reporter->ops->recover &&
+           nla_put_u64_64bit(msg, DEVLINK_ATTR_HEALTH_REPORTER_GRACEFUL_PERIOD,
+                             reporter->graceful_period,
+                             DEVLINK_ATTR_PAD))
+               goto reporter_nest_cancel;
+       if (reporter->ops->recover &&
+           nla_put_u8(msg, DEVLINK_ATTR_HEALTH_REPORTER_AUTO_RECOVER,
+                      reporter->auto_recover))
+               goto reporter_nest_cancel;
+       if (reporter->dump_fmsg &&
+           nla_put_u64_64bit(msg, DEVLINK_ATTR_HEALTH_REPORTER_DUMP_TS,
+                             jiffies_to_msecs(reporter->dump_ts),
+                             DEVLINK_ATTR_PAD))
+               goto reporter_nest_cancel;
+       if (reporter->dump_fmsg &&
+           nla_put_u64_64bit(msg, DEVLINK_ATTR_HEALTH_REPORTER_DUMP_TS_NS,
+                             reporter->dump_real_ts, DEVLINK_ATTR_PAD))
+               goto reporter_nest_cancel;
+
+       nla_nest_end(msg, reporter_attr);
+       genlmsg_end(msg, hdr);
+       return 0;
+
+reporter_nest_cancel:
+       nla_nest_end(msg, reporter_attr);
+genlmsg_cancel:
+       genlmsg_cancel(msg, hdr);
+       return -EMSGSIZE;
+}
+
+static void devlink_recover_notify(struct devlink_health_reporter *reporter,
+                                  enum devlink_command cmd)
+{
+       struct sk_buff *msg;
+       int err;
+
+       WARN_ON(cmd != DEVLINK_CMD_HEALTH_REPORTER_RECOVER);
+
+       msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+       if (!msg)
                return;
 
-       if (reporter->health_state == state)
+       err = devlink_nl_health_reporter_fill(msg, reporter->devlink,
+                                             reporter, cmd, 0, 0, 0);
+       if (err) {
+               nlmsg_free(msg);
                return;
+       }
 
-       reporter->health_state = state;
-       trace_devlink_health_reporter_state_update(reporter->devlink,
-                                                  reporter->ops->name, state);
+       genlmsg_multicast_netns(&devlink_nl_family,
+                               devlink_net(reporter->devlink),
+                               msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL);
 }
-EXPORT_SYMBOL_GPL(devlink_health_reporter_state_update);
+
+void
+devlink_health_reporter_recovery_done(struct devlink_health_reporter *reporter)
+{
+       reporter->recovery_count++;
+       reporter->last_recovery_ts = jiffies;
+}
+EXPORT_SYMBOL_GPL(devlink_health_reporter_recovery_done);
 
 static int
 devlink_health_reporter_recover(struct devlink_health_reporter *reporter,
@@ -4876,9 +4960,9 @@ devlink_health_reporter_recover(struct devlink_health_reporter *reporter,
        if (err)
                return err;
 
-       reporter->recovery_count++;
+       devlink_health_reporter_recovery_done(reporter);
        reporter->health_state = DEVLINK_HEALTH_REPORTER_STATE_HEALTHY;
-       reporter->last_recovery_ts = jiffies;
+       devlink_recover_notify(reporter, DEVLINK_CMD_HEALTH_REPORTER_RECOVER);
 
        return 0;
 }
@@ -4945,6 +5029,7 @@ int devlink_health_report(struct devlink_health_reporter *reporter,
        reporter->error_count++;
        prev_health_state = reporter->health_state;
        reporter->health_state = DEVLINK_HEALTH_REPORTER_STATE_ERROR;
+       devlink_recover_notify(reporter, DEVLINK_CMD_HEALTH_REPORTER_RECOVER);
 
        /* abort if the previous error wasn't recovered */
        if (reporter->auto_recover &&
@@ -5027,68 +5112,23 @@ devlink_health_reporter_put(struct devlink_health_reporter *reporter)
        refcount_dec(&reporter->refcount);
 }
 
-static int
-devlink_nl_health_reporter_fill(struct sk_buff *msg,
-                               struct devlink *devlink,
-                               struct devlink_health_reporter *reporter,
-                               enum devlink_command cmd, u32 portid,
-                               u32 seq, int flags)
+void
+devlink_health_reporter_state_update(struct devlink_health_reporter *reporter,
+                                    enum devlink_health_reporter_state state)
 {
-       struct nlattr *reporter_attr;
-       void *hdr;
-
-       hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
-       if (!hdr)
-               return -EMSGSIZE;
-
-       if (devlink_nl_put_handle(msg, devlink))
-               goto genlmsg_cancel;
-
-       reporter_attr = nla_nest_start_noflag(msg,
-                                             DEVLINK_ATTR_HEALTH_REPORTER);
-       if (!reporter_attr)
-               goto genlmsg_cancel;
-       if (nla_put_string(msg, DEVLINK_ATTR_HEALTH_REPORTER_NAME,
-                          reporter->ops->name))
-               goto reporter_nest_cancel;
-       if (nla_put_u8(msg, DEVLINK_ATTR_HEALTH_REPORTER_STATE,
-                      reporter->health_state))
-               goto reporter_nest_cancel;
-       if (nla_put_u64_64bit(msg, DEVLINK_ATTR_HEALTH_REPORTER_ERR_COUNT,
-                             reporter->error_count, DEVLINK_ATTR_PAD))
-               goto reporter_nest_cancel;
-       if (nla_put_u64_64bit(msg, DEVLINK_ATTR_HEALTH_REPORTER_RECOVER_COUNT,
-                             reporter->recovery_count, DEVLINK_ATTR_PAD))
-               goto reporter_nest_cancel;
-       if (reporter->ops->recover &&
-           nla_put_u64_64bit(msg, DEVLINK_ATTR_HEALTH_REPORTER_GRACEFUL_PERIOD,
-                             reporter->graceful_period,
-                             DEVLINK_ATTR_PAD))
-               goto reporter_nest_cancel;
-       if (reporter->ops->recover &&
-           nla_put_u8(msg, DEVLINK_ATTR_HEALTH_REPORTER_AUTO_RECOVER,
-                      reporter->auto_recover))
-               goto reporter_nest_cancel;
-       if (reporter->dump_fmsg &&
-           nla_put_u64_64bit(msg, DEVLINK_ATTR_HEALTH_REPORTER_DUMP_TS,
-                             jiffies_to_msecs(reporter->dump_ts),
-                             DEVLINK_ATTR_PAD))
-               goto reporter_nest_cancel;
-       if (reporter->dump_fmsg &&
-           nla_put_u64_64bit(msg, DEVLINK_ATTR_HEALTH_REPORTER_DUMP_TS_NS,
-                             reporter->dump_real_ts, DEVLINK_ATTR_PAD))
-               goto reporter_nest_cancel;
+       if (WARN_ON(state != DEVLINK_HEALTH_REPORTER_STATE_HEALTHY &&
+                   state != DEVLINK_HEALTH_REPORTER_STATE_ERROR))
+               return;
 
-       nla_nest_end(msg, reporter_attr);
-       genlmsg_end(msg, hdr);
-       return 0;
+       if (reporter->health_state == state)
+               return;
 
-reporter_nest_cancel:
-       nla_nest_end(msg, reporter_attr);
-genlmsg_cancel:
-       genlmsg_cancel(msg, hdr);
-       return -EMSGSIZE;
+       reporter->health_state = state;
+       trace_devlink_health_reporter_state_update(reporter->devlink,
+                                                  reporter->ops->name, state);
+       devlink_recover_notify(reporter, DEVLINK_CMD_HEALTH_REPORTER_RECOVER);
 }
+EXPORT_SYMBOL_GPL(devlink_health_reporter_state_update);
 
 static int devlink_nl_cmd_health_reporter_get_doit(struct sk_buff *skb,
                                                   struct genl_info *info)
@@ -7674,6 +7714,9 @@ static const struct devlink_trap devlink_trap_generic[] = {
        DEVLINK_TRAP(REJECT_ROUTE, EXCEPTION),
        DEVLINK_TRAP(IPV4_LPM_UNICAST_MISS, EXCEPTION),
        DEVLINK_TRAP(IPV6_LPM_UNICAST_MISS, EXCEPTION),
+       DEVLINK_TRAP(NON_ROUTABLE, DROP),
+       DEVLINK_TRAP(DECAP_ERROR, EXCEPTION),
+       DEVLINK_TRAP(OVERLAY_SMAC_MC, DROP),
 };
 
 #define DEVLINK_TRAP_GROUP(_id)                                                      \
@@ -7686,6 +7729,7 @@ static const struct devlink_trap_group devlink_trap_group_generic[] = {
        DEVLINK_TRAP_GROUP(L2_DROPS),
        DEVLINK_TRAP_GROUP(L3_DROPS),
        DEVLINK_TRAP_GROUP(BUFFER_DROPS),
+       DEVLINK_TRAP_GROUP(TUNNEL_DROPS),
 };
 
 static int devlink_trap_generic_verify(const struct devlink_trap *trap)