cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

metrics.c (2209B)


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