On 7/8/20 7:30 PM, Hangbin Liu wrote:
> This patch is for xdp multicast support. In this implementation we
> add a new helper to accept two maps: forward map and exclude map.
> We will redirect the packet to all the interfaces in *forward map*, but
> exclude the interfaces that in *exclude map*.
> 

good feature. I bet we could use this to create a simpler xdp dumper -
redirect to an xdpmon device which converts to an skb and passes to any
attached sockets.


> diff --git a/kernel/bpf/devmap.c b/kernel/bpf/devmap.c
> index 10abb06065bb..617a51391971 100644
> --- a/kernel/bpf/devmap.c
> +++ b/kernel/bpf/devmap.c
> @@ -512,6 +512,160 @@ int dev_map_enqueue(struct bpf_dtab_netdev *dst, struct 
> xdp_buff *xdp,
>       return __xdp_enqueue(dev, xdp, dev_rx);
>  }
>  
> +/* Use direct call in fast path instead of map->ops->map_get_next_key() */
> +static int devmap_get_next_key(struct bpf_map *map, void *key, void 
> *next_key)
> +{
> +
> +     switch (map->map_type) {
> +     case BPF_MAP_TYPE_DEVMAP:
> +             return dev_map_get_next_key(map, key, next_key);
> +     case BPF_MAP_TYPE_DEVMAP_HASH:
> +             return dev_map_hash_get_next_key(map, key, next_key);
> +     default:
> +             break;
> +     }
> +
> +     return -ENOENT;
> +}
> +
> +bool dev_in_exclude_map(struct bpf_dtab_netdev *obj, struct bpf_map *map,
> +                     int exclude_ifindex)
> +{
> +     struct bpf_dtab_netdev *ex_obj = NULL;
> +     u32 key, next_key;
> +     int err;
> +
> +     if (obj->dev->ifindex == exclude_ifindex)
> +             return true;
> +
> +     if (!map)
> +             return false;
> +
> +     err = devmap_get_next_key(map, NULL, &key);
> +     if (err)
> +             return false;
> +
> +     for (;;) {
> +             switch (map->map_type) {
> +             case BPF_MAP_TYPE_DEVMAP:
> +                     ex_obj = __dev_map_lookup_elem(map, key);
> +                     break;
> +             case BPF_MAP_TYPE_DEVMAP_HASH:
> +                     ex_obj = __dev_map_hash_lookup_elem(map, key);
> +                     break;
> +             default:
> +                     break;
> +             }
> +
> +             if (ex_obj && ex_obj->dev->ifindex == obj->dev->ifindex)

I'm probably missing something fundamental, but why do you need to walk
the keys? Why not just do a lookup on the device index?

> +                     return true;
> +
> +             err = devmap_get_next_key(map, &key, &next_key);
> +             if (err)
> +                     break;
> +
> +             key = next_key;
> +     }
> +
> +     return false;
> +}
> +




> @@ -3741,6 +3810,34 @@ static const struct bpf_func_proto 
> bpf_xdp_redirect_map_proto = {
>       .arg3_type      = ARG_ANYTHING,
>  };
>  
> +BPF_CALL_3(bpf_xdp_redirect_map_multi, struct bpf_map *, map,
> +        struct bpf_map *, ex_map, u64, flags)
> +{
> +     struct bpf_redirect_info *ri = this_cpu_ptr(&bpf_redirect_info);
> +
> +     if (unlikely(!map || flags > BPF_F_EXCLUDE_INGRESS))

If flags is a bitfield, the check should be:
    flags & ~BPF_F_EXCLUDE_INGRESS

Reply via email to