Add 'struct bpf_devmap_val' to formalize the expected values that can be passed in for a DEVMAP. Update devmap code to use the struct.
Unified · Split
| @@ -60,12 +60,18 @@ struct xdp_dev_bulk_queue { · 59 unmodified lines | |||
| 60 | unsigned int count; | 60 | unsigned int count; |
| 61 | }; | 61 | }; |
| 62 | 62 | ||
| 63 | /* DEVMAP values */ | ||
| 64 | struct bpf_devmap_val { | ||
| 65 | u32 ifindex; /* device index */ | ||
| 66 | }; | ||
| 67 | |||
| 63 | struct bpf_dtab_netdev { | 68 | struct bpf_dtab_netdev { |
| 64 | struct net_device *dev; /* must be first member, due to tracepoint */ | 69 | struct net_device *dev; /* must be first member, due to tracepoint */ |
| 65 | struct hlist_node index_hlist; | 70 | struct hlist_node index_hlist; |
| 66 | struct bpf_dtab *dtab; | 71 | struct bpf_dtab *dtab; |
| 67 | struct rcu_head rcu; | 72 | struct rcu_head rcu; |
| 68 | unsigned int idx; | 73 | unsigned int idx; |
| 74 | struct bpf_devmap_val val; | ||
| 69 | }; | 75 | }; |
| 70 | 76 | ||
| 71 | struct bpf_dtab { | 77 | struct bpf_dtab { |
| @@ -472,18 +478,15 @@ int dev_map_generic_redirect(struct bpf_dtab_netdev *dst, struct sk_buff *skb, · 400 unmodified lines | |||
| 472 | static void *dev_map_lookup_elem(struct bpf_map *map, void *key) | 478 | static void *dev_map_lookup_elem(struct bpf_map *map, void *key) |
| 473 | { | 479 | { |
| 474 | struct bpf_dtab_netdev *obj = __dev_map_lookup_elem(map, *(u32 *)key); | 480 | struct bpf_dtab_netdev *obj = __dev_map_lookup_elem(map, *(u32 *)key); |
| 475 | struct net_device *dev = obj ? obj->dev : NULL; | ||
| 476 | 481 | ||
| 477 | return dev ? &dev->ifindex : NULL; | 482 | return obj ? &obj->val : NULL; |
| 478 | } | 483 | } |
| 479 | 484 | ||
| 480 | static void *dev_map_hash_lookup_elem(struct bpf_map *map, void *key) | 485 | static void *dev_map_hash_lookup_elem(struct bpf_map *map, void *key) |
| 481 | { | 486 | { |
| 482 | struct bpf_dtab_netdev *obj = __dev_map_hash_lookup_elem(map, | 487 | struct bpf_dtab_netdev *obj = __dev_map_hash_lookup_elem(map, |
| 483 | *(u32 *)key); | 488 | *(u32 *)key); |
| 484 | struct net_device *dev = obj ? obj->dev : NULL; | 489 | return obj ? &obj->val : NULL; |
| 485 | |||
| 486 | return dev ? &dev->ifindex : NULL; | ||
| 487 | } | 490 | } |
| 488 | 491 | ||
| 489 | static void __dev_map_entry_free(struct rcu_head *rcu) | 492 | static void __dev_map_entry_free(struct rcu_head *rcu) |
| @@ -541,7 +544,7 @@ static int dev_map_hash_delete_elem(struct bpf_map *map, void *key) · 51 unmodified lines | |||
| 541 | 544 | ||
| 542 | static struct bpf_dtab_netdev *__dev_map_alloc_node(struct net *net, | 545 | static struct bpf_dtab_netdev *__dev_map_alloc_node(struct net *net, |
| 543 | struct bpf_dtab *dtab, | 546 | struct bpf_dtab *dtab, |
| 544 | u32 ifindex, | 547 | struct bpf_devmap_val *val, |
| 545 | unsigned int idx) | 548 | unsigned int idx) |
| 546 | { | 549 | { |
| 547 | struct bpf_dtab_netdev *dev; | 550 | struct bpf_dtab_netdev *dev; |
| @@ -551,16 +554,18 @@ static struct bpf_dtab_netdev *__dev_map_alloc_node(struct net *net, · 3 unmodified lines | |||
| 551 | if (!dev) | 554 | if (!dev) |
| 552 | return ERR_PTR(-ENOMEM); | 555 | return ERR_PTR(-ENOMEM); |
| 553 | 556 | ||
| 554 | dev->dev = dev_get_by_index(net, ifindex); | 557 | dev->dev = dev_get_by_index(net, val->ifindex); |
| 555 | if (!dev->dev) { | 558 | if (!dev->dev) |
| 556 | kfree(dev); | 559 | goto err_out; |
| 557 | return ERR_PTR(-EINVAL); | ||
| 558 | } | ||
| 559 | 560 | ||
| 560 | dev->idx = idx; | 561 | dev->idx = idx; |
| 561 | dev->dtab = dtab; | 562 | dev->dtab = dtab; |
| 563 | dev->val.ifindex = val->ifindex; | ||
| 562 | 564 | ||
| 563 | return dev; | 565 | return dev; |
| 566 | err_out: | ||
| 567 | kfree(dev); | ||
| 568 | return ERR_PTR(-EINVAL); | ||
| 564 | } | 569 | } |
| 565 | 570 | ||
| 566 | static int __dev_map_update_elem(struct net *net, struct bpf_map *map, | 571 | static int __dev_map_update_elem(struct net *net, struct bpf_map *map, |
| @@ -568,7 +573,7 @@ static int __dev_map_update_elem(struct net *net, struct bpf_map *map, · 1 unmodified line | |||
| 568 | { | 573 | { |
| 569 | struct bpf_dtab *dtab = container_of(map, struct bpf_dtab, map); | 574 | struct bpf_dtab *dtab = container_of(map, struct bpf_dtab, map); |
| 570 | struct bpf_dtab_netdev *dev, *old_dev; | 575 | struct bpf_dtab_netdev *dev, *old_dev; |
| 571 | u32 ifindex = *(u32 *)value; | 576 | struct bpf_devmap_val val = { }; |
| 572 | u32 i = *(u32 *)key; | 577 | u32 i = *(u32 *)key; |
| 573 | 578 | ||
| 574 | if (unlikely(map_flags > BPF_EXIST)) | 579 | if (unlikely(map_flags > BPF_EXIST)) |
| @@ -578,10 +583,13 @@ static int __dev_map_update_elem(struct net *net, struct bpf_map *map, · 3 unmodified lines | |||
| 578 | if (unlikely(map_flags == BPF_NOEXIST)) | 583 | if (unlikely(map_flags == BPF_NOEXIST)) |
| 579 | return -EEXIST; | 584 | return -EEXIST; |
| 580 | 585 | ||
| 581 | if (!ifindex) { | 586 | /* already verified value_size <= sizeof val */ |
| 587 | memcpy(&val, value, map->value_size); | ||
| 588 | |||
| 589 | if (!val.ifindex) { | ||
| 582 | dev = NULL; | 590 | dev = NULL; |
| 583 | } else { | 591 | } else { |
| 584 | dev = __dev_map_alloc_node(net, dtab, ifindex, i); | 592 | dev = __dev_map_alloc_node(net, dtab, &val, i); |
| 585 | if (IS_ERR(dev)) | 593 | if (IS_ERR(dev)) |
| 586 | return PTR_ERR(dev); | 594 | return PTR_ERR(dev); |
| 587 | } | 595 | } |
| @@ -609,12 +617,15 @@ static int __dev_map_hash_update_elem(struct net *net, struct bpf_map *map, · 21 unmodified lines | |||
| 609 | { | 617 | { |
| 610 | struct bpf_dtab *dtab = container_of(map, struct bpf_dtab, map); | 618 | struct bpf_dtab *dtab = container_of(map, struct bpf_dtab, map); |
| 611 | struct bpf_dtab_netdev *dev, *old_dev; | 619 | struct bpf_dtab_netdev *dev, *old_dev; |
| 612 | u32 ifindex = *(u32 *)value; | 620 | struct bpf_devmap_val val = { }; |
| 613 | u32 idx = *(u32 *)key; | 621 | u32 idx = *(u32 *)key; |
| 614 | unsigned long flags; | 622 | unsigned long flags; |
| 615 | int err = -EEXIST; | 623 | int err = -EEXIST; |
| 616 | 624 | ||
| 617 | if (unlikely(map_flags > BPF_EXIST || !ifindex)) | 625 | /* already verified value_size <= sizeof val */ |
| 626 | memcpy(&val, value, map->value_size); | ||
| 627 | |||
| 628 | if (unlikely(map_flags > BPF_EXIST || !val.ifindex)) | ||
| 618 | return -EINVAL; | 629 | return -EINVAL; |
| 619 | 630 | ||
| 620 | spin_lock_irqsave(&dtab->index_lock, flags); | 631 | spin_lock_irqsave(&dtab->index_lock, flags); |
| @@ -623,7 +634,7 @@ static int __dev_map_hash_update_elem(struct net *net, struct bpf_map *map, · 2 unmodified lines | |||
| 623 | if (old_dev && (map_flags & BPF_NOEXIST)) | 634 | if (old_dev && (map_flags & BPF_NOEXIST)) |
| 624 | goto out_err; | 635 | goto out_err; |
| 625 | 636 | ||
| 626 | dev = __dev_map_alloc_node(net, dtab, ifindex, idx); | 637 | dev = __dev_map_alloc_node(net, dtab, &val, idx); |
| 627 | if (IS_ERR(dev)) { | 638 | if (IS_ERR(dev)) { |
| 628 | err = PTR_ERR(dev); | 639 | err = PTR_ERR(dev); |
| 629 | goto out_err; | 640 | goto out_err; |