diff options
Diffstat (limited to 'net/core/devlink.c')
| -rw-r--r-- | net/core/devlink.c | 178 | 
1 files changed, 108 insertions, 70 deletions
diff --git a/net/core/devlink.c b/net/core/devlink.c index f76219bf0c21..ca1df0ec3c97 100644 --- a/net/core/devlink.c +++ b/net/core/devlink.c @@ -4843,22 +4843,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 +4954,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 +5023,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 +5106,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 +7708,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 +7723,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)  |