1 #include <linux/netlink.h>
2 #include <linux/rtnetlink.h>
3 #include <linux/types.h>
5 #include <net/net_namespace.h>
8 static int ip_metrics_convert(struct net
*net
, struct nlattr
*fc_mx
,
9 int fc_mx_len
, u32
*metrics
)
18 nla_for_each_attr(nla
, fc_mx
, fc_mx_len
, remaining
) {
19 int type
= nla_type(nla
);
27 if (type
== RTAX_CC_ALGO
) {
28 char tmp
[TCP_CA_NAME_MAX
];
30 nla_strlcpy(tmp
, nla
, sizeof(tmp
));
31 val
= tcp_ca_get_key_by_name(net
, tmp
, &ecn_ca
);
32 if (val
== TCP_CA_UNSPEC
)
35 if (nla_len(nla
) != sizeof(u32
))
37 val
= nla_get_u32(nla
);
39 if (type
== RTAX_ADVMSS
&& val
> 65535 - 40)
41 if (type
== RTAX_MTU
&& val
> 65535 - 15)
43 if (type
== RTAX_HOPLIMIT
&& val
> 255)
45 if (type
== RTAX_FEATURES
&& (val
& ~RTAX_FEATURE_MASK
))
47 metrics
[type
- 1] = val
;
51 metrics
[RTAX_FEATURES
- 1] |= DST_FEATURE_ECN_CA
;
56 struct dst_metrics
*ip_fib_metrics_init(struct net
*net
, struct nlattr
*fc_mx
,
59 struct dst_metrics
*fib_metrics
;
63 return (struct dst_metrics
*)&dst_default_metrics
;
65 fib_metrics
= kzalloc(sizeof(*fib_metrics
), GFP_KERNEL
);
66 if (unlikely(!fib_metrics
))
67 return ERR_PTR(-ENOMEM
);
69 err
= ip_metrics_convert(net
, fc_mx
, fc_mx_len
, fib_metrics
->metrics
);
71 refcount_set(&fib_metrics
->refcnt
, 1);
74 fib_metrics
= ERR_PTR(err
);
79 EXPORT_SYMBOL_GPL(ip_fib_metrics_init
);