Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net: add extack arg to lwtunnel build state

Pass extack arg down to lwtunnel_build_state and the build_state callbacks.
Add messages for failures in lwtunnel_build_state, and add the extarg to
nla_parse where possible in the build_state callbacks.

Signed-off-by: David Ahern <dsahern@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

David Ahern and committed by
David S. Miller
9ae28727 c255bd68

+67 -30
+10
include/linux/netlink.h
··· 102 102 (extack)->bad_attr = (attr); \ 103 103 } while (0) 104 104 105 + #define NL_SET_ERR_MSG_ATTR(extack, attr, msg) do { \ 106 + static const char __msg[] = (msg); \ 107 + struct netlink_ext_ack *__extack = (extack); \ 108 + \ 109 + if (__extack) { \ 110 + __extack->_msg = __msg; \ 111 + __extack->bad_attr = (attr); \ 112 + } \ 113 + } while (0) 114 + 105 115 extern void netlink_kernel_release(struct sock *sk); 106 116 extern int __netlink_change_ngroups(struct sock *sk, unsigned int groups); 107 117 extern int netlink_change_ngroups(struct sock *sk, unsigned int groups);
+6 -3
include/net/lwtunnel.h
··· 35 35 struct lwtunnel_encap_ops { 36 36 int (*build_state)(struct nlattr *encap, 37 37 unsigned int family, const void *cfg, 38 - struct lwtunnel_state **ts); 38 + struct lwtunnel_state **ts, 39 + struct netlink_ext_ack *extack); 39 40 void (*destroy_state)(struct lwtunnel_state *lws); 40 41 int (*output)(struct net *net, struct sock *sk, struct sk_buff *skb); 41 42 int (*input)(struct sk_buff *skb); ··· 115 114 int lwtunnel_build_state(u16 encap_type, 116 115 struct nlattr *encap, 117 116 unsigned int family, const void *cfg, 118 - struct lwtunnel_state **lws); 117 + struct lwtunnel_state **lws, 118 + struct netlink_ext_ack *extack); 119 119 int lwtunnel_fill_encap(struct sk_buff *skb, 120 120 struct lwtunnel_state *lwtstate); 121 121 int lwtunnel_get_encap_size(struct lwtunnel_state *lwtstate); ··· 194 192 static inline int lwtunnel_build_state(u16 encap_type, 195 193 struct nlattr *encap, 196 194 unsigned int family, const void *cfg, 197 - struct lwtunnel_state **lws) 195 + struct lwtunnel_state **lws, 196 + struct netlink_ext_ack *extack) 198 197 { 199 198 return -EOPNOTSUPP; 200 199 }
+3 -2
net/core/lwt_bpf.c
··· 240 240 241 241 static int bpf_build_state(struct nlattr *nla, 242 242 unsigned int family, const void *cfg, 243 - struct lwtunnel_state **ts) 243 + struct lwtunnel_state **ts, 244 + struct netlink_ext_ack *extack) 244 245 { 245 246 struct nlattr *tb[LWT_BPF_MAX + 1]; 246 247 struct lwtunnel_state *newts; ··· 251 250 if (family != AF_INET && family != AF_INET6) 252 251 return -EAFNOSUPPORT; 253 252 254 - ret = nla_parse_nested(tb, LWT_BPF_MAX, nla, bpf_nl_policy, NULL); 253 + ret = nla_parse_nested(tb, LWT_BPF_MAX, nla, bpf_nl_policy, extack); 255 254 if (ret < 0) 256 255 return ret; 257 256
+17 -3
net/core/lwtunnel.c
··· 103 103 104 104 int lwtunnel_build_state(u16 encap_type, 105 105 struct nlattr *encap, unsigned int family, 106 - const void *cfg, struct lwtunnel_state **lws) 106 + const void *cfg, struct lwtunnel_state **lws, 107 + struct netlink_ext_ack *extack) 107 108 { 108 109 const struct lwtunnel_encap_ops *ops; 110 + bool found = false; 109 111 int ret = -EINVAL; 110 112 111 113 if (encap_type == LWTUNNEL_ENCAP_NONE || 112 - encap_type > LWTUNNEL_ENCAP_MAX) 114 + encap_type > LWTUNNEL_ENCAP_MAX) { 115 + NL_SET_ERR_MSG_ATTR(extack, encap, 116 + "Unknown LWT encapsulation type"); 113 117 return ret; 118 + } 114 119 115 120 ret = -EOPNOTSUPP; 116 121 rcu_read_lock(); 117 122 ops = rcu_dereference(lwtun_encaps[encap_type]); 118 123 if (likely(ops && ops->build_state && try_module_get(ops->owner))) { 119 - ret = ops->build_state(encap, family, cfg, lws); 124 + found = true; 125 + ret = ops->build_state(encap, family, cfg, lws, extack); 120 126 if (ret) 121 127 module_put(ops->owner); 122 128 } 123 129 rcu_read_unlock(); 130 + 131 + /* don't rely on -EOPNOTSUPP to detect match as build_state 132 + * handlers could return it 133 + */ 134 + if (!found) { 135 + NL_SET_ERR_MSG_ATTR(extack, encap, 136 + "LWT encapsulation type not supported"); 137 + } 124 138 125 139 return ret; 126 140 }
+2 -1
net/ipv4/fib_lookup.h
··· 30 30 void fib_release_info(struct fib_info *); 31 31 struct fib_info *fib_create_info(struct fib_config *cfg, 32 32 struct netlink_ext_ack *extack); 33 - int fib_nh_match(struct fib_config *cfg, struct fib_info *fi); 33 + int fib_nh_match(struct fib_config *cfg, struct fib_info *fi, 34 + struct netlink_ext_ack *extack); 34 35 int fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event, u32 tb_id, 35 36 u8 type, __be32 dst, int dst_len, u8 tos, struct fib_info *fi, 36 37 unsigned int);
+11 -9
net/ipv4/fib_semantics.c
··· 532 532 ret = lwtunnel_build_state(nla_get_u16( 533 533 nla_entype), 534 534 nla, AF_INET, cfg, 535 - &lwtstate); 535 + &lwtstate, extack); 536 536 if (ret) 537 537 goto errout; 538 538 nexthop_nh->nh_lwtstate = ··· 614 614 static int fib_encap_match(u16 encap_type, 615 615 struct nlattr *encap, 616 616 const struct fib_nh *nh, 617 - const struct fib_config *cfg) 617 + const struct fib_config *cfg, 618 + struct netlink_ext_ack *extack) 618 619 { 619 620 struct lwtunnel_state *lwtstate; 620 621 int ret, result = 0; ··· 623 622 if (encap_type == LWTUNNEL_ENCAP_NONE) 624 623 return 0; 625 624 626 - ret = lwtunnel_build_state(encap_type, encap, 627 - AF_INET, cfg, &lwtstate); 625 + ret = lwtunnel_build_state(encap_type, encap, AF_INET, 626 + cfg, &lwtstate, extack); 628 627 if (!ret) { 629 628 result = lwtunnel_cmp_encap(lwtstate, nh->nh_lwtstate); 630 629 lwtstate_free(lwtstate); ··· 633 632 return result; 634 633 } 635 634 636 - int fib_nh_match(struct fib_config *cfg, struct fib_info *fi) 635 + int fib_nh_match(struct fib_config *cfg, struct fib_info *fi, 636 + struct netlink_ext_ack *extack) 637 637 { 638 638 #ifdef CONFIG_IP_ROUTE_MULTIPATH 639 639 struct rtnexthop *rtnh; ··· 646 644 647 645 if (cfg->fc_oif || cfg->fc_gw) { 648 646 if (cfg->fc_encap) { 649 - if (fib_encap_match(cfg->fc_encap_type, 650 - cfg->fc_encap, fi->fib_nh, cfg)) 651 - return 1; 647 + if (fib_encap_match(cfg->fc_encap_type, cfg->fc_encap, 648 + fi->fib_nh, cfg, extack)) 649 + return 1; 652 650 } 653 651 if ((!cfg->fc_oif || cfg->fc_oif == fi->fib_nh->nh_oif) && 654 652 (!cfg->fc_gw || cfg->fc_gw == fi->fib_nh->nh_gw)) ··· 1150 1148 } 1151 1149 err = lwtunnel_build_state(cfg->fc_encap_type, 1152 1150 cfg->fc_encap, AF_INET, cfg, 1153 - &lwtstate); 1151 + &lwtstate, extack); 1154 1152 if (err) 1155 1153 goto failure; 1156 1154
+1 -1
net/ipv4/fib_trie.c
··· 1562 1562 fi->fib_prefsrc == cfg->fc_prefsrc) && 1563 1563 (!cfg->fc_protocol || 1564 1564 fi->fib_protocol == cfg->fc_protocol) && 1565 - fib_nh_match(cfg, fi) == 0) { 1565 + fib_nh_match(cfg, fi, extack) == 0) { 1566 1566 fa_to_delete = fa; 1567 1567 break; 1568 1568 }
+7 -4
net/ipv4/ip_tunnel_core.c
··· 228 228 229 229 static int ip_tun_build_state(struct nlattr *attr, 230 230 unsigned int family, const void *cfg, 231 - struct lwtunnel_state **ts) 231 + struct lwtunnel_state **ts, 232 + struct netlink_ext_ack *extack) 232 233 { 233 234 struct ip_tunnel_info *tun_info; 234 235 struct lwtunnel_state *new_state; 235 236 struct nlattr *tb[LWTUNNEL_IP_MAX + 1]; 236 237 int err; 237 238 238 - err = nla_parse_nested(tb, LWTUNNEL_IP_MAX, attr, ip_tun_policy, NULL); 239 + err = nla_parse_nested(tb, LWTUNNEL_IP_MAX, attr, ip_tun_policy, 240 + extack); 239 241 if (err < 0) 240 242 return err; 241 243 ··· 327 325 328 326 static int ip6_tun_build_state(struct nlattr *attr, 329 327 unsigned int family, const void *cfg, 330 - struct lwtunnel_state **ts) 328 + struct lwtunnel_state **ts, 329 + struct netlink_ext_ack *extack) 331 330 { 332 331 struct ip_tunnel_info *tun_info; 333 332 struct lwtunnel_state *new_state; ··· 336 333 int err; 337 334 338 335 err = nla_parse_nested(tb, LWTUNNEL_IP6_MAX, attr, ip6_tun_policy, 339 - NULL); 336 + extack); 340 337 if (err < 0) 341 338 return err; 342 339
+3 -2
net/ipv6/ila/ila_lwt.c
··· 117 117 118 118 static int ila_build_state(struct nlattr *nla, 119 119 unsigned int family, const void *cfg, 120 - struct lwtunnel_state **ts) 120 + struct lwtunnel_state **ts, 121 + struct netlink_ext_ack *extack) 121 122 { 122 123 struct ila_lwt *ilwt; 123 124 struct ila_params *p; ··· 147 146 return -EINVAL; 148 147 } 149 148 150 - ret = nla_parse_nested(tb, ILA_ATTR_MAX, nla, ila_nl_policy, NULL); 149 + ret = nla_parse_nested(tb, ILA_ATTR_MAX, nla, ila_nl_policy, extack); 151 150 if (ret < 0) 152 151 return ret; 153 152
+1 -1
net/ipv6/route.c
··· 1939 1939 1940 1940 err = lwtunnel_build_state(cfg->fc_encap_type, 1941 1941 cfg->fc_encap, AF_INET6, cfg, 1942 - &lwtstate); 1942 + &lwtstate, extack); 1943 1943 if (err) 1944 1944 goto out; 1945 1945 rt->dst.lwtstate = lwtstate_get(lwtstate);
+3 -2
net/ipv6/seg6_iptunnel.c
··· 326 326 327 327 static int seg6_build_state(struct nlattr *nla, 328 328 unsigned int family, const void *cfg, 329 - struct lwtunnel_state **ts) 329 + struct lwtunnel_state **ts, 330 + struct netlink_ext_ack *extack) 330 331 { 331 332 struct nlattr *tb[SEG6_IPTUNNEL_MAX + 1]; 332 333 struct seg6_iptunnel_encap *tuninfo; ··· 337 336 int err; 338 337 339 338 err = nla_parse_nested(tb, SEG6_IPTUNNEL_MAX, nla, 340 - seg6_iptunnel_policy, NULL); 339 + seg6_iptunnel_policy, extack); 341 340 342 341 if (err < 0) 343 342 return err;
+3 -2
net/mpls/mpls_iptunnel.c
··· 159 159 160 160 static int mpls_build_state(struct nlattr *nla, 161 161 unsigned int family, const void *cfg, 162 - struct lwtunnel_state **ts) 162 + struct lwtunnel_state **ts, 163 + struct netlink_ext_ack *extack) 163 164 { 164 165 struct mpls_iptunnel_encap *tun_encap_info; 165 166 struct nlattr *tb[MPLS_IPTUNNEL_MAX + 1]; ··· 169 168 int ret; 170 169 171 170 ret = nla_parse_nested(tb, MPLS_IPTUNNEL_MAX, nla, 172 - mpls_iptunnel_policy, NULL); 171 + mpls_iptunnel_policy, extack); 173 172 if (ret < 0) 174 173 return ret; 175 174