Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  2) #include <linux/netlink.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  3) #include <linux/rtnetlink.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  4) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  5) #include <net/ip.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  6) #include <net/net_namespace.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  7) #include <net/tcp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  8) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  9) static int ip_metrics_convert(struct net *net, struct nlattr *fc_mx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) 			      int fc_mx_len, u32 *metrics,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) 			      struct netlink_ext_ack *extack)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) 	bool ecn_ca = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) 	struct nlattr *nla;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) 	int remaining;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) 	if (!fc_mx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) 	nla_for_each_attr(nla, fc_mx, fc_mx_len, remaining) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) 		int type = nla_type(nla);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) 		u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) 		if (!type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) 		if (type > RTAX_MAX) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) 			NL_SET_ERR_MSG(extack, "Invalid metric type");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) 			return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) 		if (type == RTAX_CC_ALGO) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) 			char tmp[TCP_CA_NAME_MAX];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) 			nla_strlcpy(tmp, nla, sizeof(tmp));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) 			val = tcp_ca_get_key_by_name(net, tmp, &ecn_ca);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) 			if (val == TCP_CA_UNSPEC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) 				NL_SET_ERR_MSG(extack, "Unknown tcp congestion algorithm");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) 				return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) 			if (nla_len(nla) != sizeof(u32)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) 				NL_SET_ERR_MSG_ATTR(extack, nla,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) 						    "Invalid attribute in metrics");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) 				return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) 			val = nla_get_u32(nla);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) 		if (type == RTAX_ADVMSS && val > 65535 - 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) 			val = 65535 - 40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) 		if (type == RTAX_MTU && val > 65535 - 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) 			val = 65535 - 15;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) 		if (type == RTAX_HOPLIMIT && val > 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) 			val = 255;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) 		if (type == RTAX_FEATURES && (val & ~RTAX_FEATURE_MASK)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) 			NL_SET_ERR_MSG(extack, "Unknown flag set in feature mask in metrics attribute");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) 			return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) 		metrics[type - 1] = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) 	if (ecn_ca)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) 		metrics[RTAX_FEATURES - 1] |= DST_FEATURE_ECN_CA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) struct dst_metrics *ip_fib_metrics_init(struct net *net, struct nlattr *fc_mx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) 					int fc_mx_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) 					struct netlink_ext_ack *extack)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) 	struct dst_metrics *fib_metrics;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) 	if (!fc_mx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) 		return (struct dst_metrics *)&dst_default_metrics;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) 	fib_metrics = kzalloc(sizeof(*fib_metrics), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) 	if (unlikely(!fib_metrics))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) 		return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) 	err = ip_metrics_convert(net, fc_mx, fc_mx_len, fib_metrics->metrics,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) 				 extack);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) 	if (!err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) 		refcount_set(&fib_metrics->refcnt, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) 		kfree(fib_metrics);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) 		fib_metrics = ERR_PTR(err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) 	return fib_metrics;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) EXPORT_SYMBOL_GPL(ip_fib_metrics_init);