diff options
Diffstat (limited to 'net/core/rtnetlink.c')
-rw-r--r-- | net/core/rtnetlink.c | 81 |
1 files changed, 47 insertions, 34 deletions
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index bcb0f610ee42..49a279a7cc15 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c | |||
@@ -899,8 +899,7 @@ static size_t rtnl_port_size(const struct net_device *dev, | |||
899 | static size_t rtnl_xdp_size(void) | 899 | static size_t rtnl_xdp_size(void) |
900 | { | 900 | { |
901 | size_t xdp_size = nla_total_size(0) + /* nest IFLA_XDP */ | 901 | size_t xdp_size = nla_total_size(0) + /* nest IFLA_XDP */ |
902 | nla_total_size(1) + /* XDP_ATTACHED */ | 902 | nla_total_size(1); /* XDP_ATTACHED */ |
903 | nla_total_size(4); /* XDP_FLAGS */ | ||
904 | 903 | ||
905 | return xdp_size; | 904 | return xdp_size; |
906 | } | 905 | } |
@@ -1247,37 +1246,34 @@ static int rtnl_fill_link_ifmap(struct sk_buff *skb, struct net_device *dev) | |||
1247 | return 0; | 1246 | return 0; |
1248 | } | 1247 | } |
1249 | 1248 | ||
1249 | static u8 rtnl_xdp_attached_mode(struct net_device *dev) | ||
1250 | { | ||
1251 | const struct net_device_ops *ops = dev->netdev_ops; | ||
1252 | |||
1253 | ASSERT_RTNL(); | ||
1254 | |||
1255 | if (rcu_access_pointer(dev->xdp_prog)) | ||
1256 | return XDP_ATTACHED_SKB; | ||
1257 | if (ops->ndo_xdp && __dev_xdp_attached(dev, ops->ndo_xdp)) | ||
1258 | return XDP_ATTACHED_DRV; | ||
1259 | |||
1260 | return XDP_ATTACHED_NONE; | ||
1261 | } | ||
1262 | |||
1250 | static int rtnl_xdp_fill(struct sk_buff *skb, struct net_device *dev) | 1263 | static int rtnl_xdp_fill(struct sk_buff *skb, struct net_device *dev) |
1251 | { | 1264 | { |
1252 | struct nlattr *xdp; | 1265 | struct nlattr *xdp; |
1253 | u32 xdp_flags = 0; | ||
1254 | u8 val = 0; | ||
1255 | int err; | 1266 | int err; |
1256 | 1267 | ||
1257 | xdp = nla_nest_start(skb, IFLA_XDP); | 1268 | xdp = nla_nest_start(skb, IFLA_XDP); |
1258 | if (!xdp) | 1269 | if (!xdp) |
1259 | return -EMSGSIZE; | 1270 | return -EMSGSIZE; |
1260 | if (rcu_access_pointer(dev->xdp_prog)) { | 1271 | |
1261 | xdp_flags = XDP_FLAGS_SKB_MODE; | 1272 | err = nla_put_u8(skb, IFLA_XDP_ATTACHED, |
1262 | val = 1; | 1273 | rtnl_xdp_attached_mode(dev)); |
1263 | } else if (dev->netdev_ops->ndo_xdp) { | ||
1264 | struct netdev_xdp xdp_op = {}; | ||
1265 | |||
1266 | xdp_op.command = XDP_QUERY_PROG; | ||
1267 | err = dev->netdev_ops->ndo_xdp(dev, &xdp_op); | ||
1268 | if (err) | ||
1269 | goto err_cancel; | ||
1270 | val = xdp_op.prog_attached; | ||
1271 | } | ||
1272 | err = nla_put_u8(skb, IFLA_XDP_ATTACHED, val); | ||
1273 | if (err) | 1274 | if (err) |
1274 | goto err_cancel; | 1275 | goto err_cancel; |
1275 | 1276 | ||
1276 | if (xdp_flags) { | ||
1277 | err = nla_put_u32(skb, IFLA_XDP_FLAGS, xdp_flags); | ||
1278 | if (err) | ||
1279 | goto err_cancel; | ||
1280 | } | ||
1281 | nla_nest_end(skb, xdp); | 1277 | nla_nest_end(skb, xdp); |
1282 | return 0; | 1278 | return 0; |
1283 | 1279 | ||
@@ -1631,13 +1627,13 @@ static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb) | |||
1631 | cb->nlh->nlmsg_seq, 0, | 1627 | cb->nlh->nlmsg_seq, 0, |
1632 | flags, | 1628 | flags, |
1633 | ext_filter_mask); | 1629 | ext_filter_mask); |
1634 | /* If we ran out of room on the first message, | ||
1635 | * we're in trouble | ||
1636 | */ | ||
1637 | WARN_ON((err == -EMSGSIZE) && (skb->len == 0)); | ||
1638 | 1630 | ||
1639 | if (err < 0) | 1631 | if (err < 0) { |
1640 | goto out; | 1632 | if (likely(skb->len)) |
1633 | goto out; | ||
1634 | |||
1635 | goto out_err; | ||
1636 | } | ||
1641 | 1637 | ||
1642 | nl_dump_check_consistent(cb, nlmsg_hdr(skb)); | 1638 | nl_dump_check_consistent(cb, nlmsg_hdr(skb)); |
1643 | cont: | 1639 | cont: |
@@ -1645,10 +1641,12 @@ cont: | |||
1645 | } | 1641 | } |
1646 | } | 1642 | } |
1647 | out: | 1643 | out: |
1644 | err = skb->len; | ||
1645 | out_err: | ||
1648 | cb->args[1] = idx; | 1646 | cb->args[1] = idx; |
1649 | cb->args[0] = h; | 1647 | cb->args[0] = h; |
1650 | 1648 | ||
1651 | return skb->len; | 1649 | return err; |
1652 | } | 1650 | } |
1653 | 1651 | ||
1654 | int rtnl_nla_parse_ifla(struct nlattr **tb, const struct nlattr *head, int len, | 1652 | int rtnl_nla_parse_ifla(struct nlattr **tb, const struct nlattr *head, int len, |
@@ -2199,6 +2197,11 @@ static int do_setlink(const struct sk_buff *skb, | |||
2199 | err = -EINVAL; | 2197 | err = -EINVAL; |
2200 | goto errout; | 2198 | goto errout; |
2201 | } | 2199 | } |
2200 | if ((xdp_flags & XDP_FLAGS_SKB_MODE) && | ||
2201 | (xdp_flags & XDP_FLAGS_DRV_MODE)) { | ||
2202 | err = -EINVAL; | ||
2203 | goto errout; | ||
2204 | } | ||
2202 | } | 2205 | } |
2203 | 2206 | ||
2204 | if (xdp[IFLA_XDP_FD]) { | 2207 | if (xdp[IFLA_XDP_FD]) { |
@@ -3452,8 +3455,12 @@ static int rtnl_bridge_getlink(struct sk_buff *skb, struct netlink_callback *cb) | |||
3452 | err = br_dev->netdev_ops->ndo_bridge_getlink( | 3455 | err = br_dev->netdev_ops->ndo_bridge_getlink( |
3453 | skb, portid, seq, dev, | 3456 | skb, portid, seq, dev, |
3454 | filter_mask, NLM_F_MULTI); | 3457 | filter_mask, NLM_F_MULTI); |
3455 | if (err < 0 && err != -EOPNOTSUPP) | 3458 | if (err < 0 && err != -EOPNOTSUPP) { |
3456 | break; | 3459 | if (likely(skb->len)) |
3460 | break; | ||
3461 | |||
3462 | goto out_err; | ||
3463 | } | ||
3457 | } | 3464 | } |
3458 | idx++; | 3465 | idx++; |
3459 | } | 3466 | } |
@@ -3464,16 +3471,22 @@ static int rtnl_bridge_getlink(struct sk_buff *skb, struct netlink_callback *cb) | |||
3464 | seq, dev, | 3471 | seq, dev, |
3465 | filter_mask, | 3472 | filter_mask, |
3466 | NLM_F_MULTI); | 3473 | NLM_F_MULTI); |
3467 | if (err < 0 && err != -EOPNOTSUPP) | 3474 | if (err < 0 && err != -EOPNOTSUPP) { |
3468 | break; | 3475 | if (likely(skb->len)) |
3476 | break; | ||
3477 | |||
3478 | goto out_err; | ||
3479 | } | ||
3469 | } | 3480 | } |
3470 | idx++; | 3481 | idx++; |
3471 | } | 3482 | } |
3472 | } | 3483 | } |
3484 | err = skb->len; | ||
3485 | out_err: | ||
3473 | rcu_read_unlock(); | 3486 | rcu_read_unlock(); |
3474 | cb->args[0] = idx; | 3487 | cb->args[0] = idx; |
3475 | 3488 | ||
3476 | return skb->len; | 3489 | return err; |
3477 | } | 3490 | } |
3478 | 3491 | ||
3479 | static inline size_t bridge_nlmsg_size(void) | 3492 | static inline size_t bridge_nlmsg_size(void) |