mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	net: implement XDP_REDIRECT for xdp generic
Add support for redirect to xdp generic creating a fall back for devices that do not yet have support and allowing test infrastructure using veth pairs to be built. Signed-off-by: John Fastabend <john.fastabend@gmail.com> Tested-by: Andy Gospodarek <andy@greyhouse.net> Acked-by: Daniel Borkmann <daniel@iogearbox.net> Acked-by: Jesper Dangaard Brouer <brouer@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
							parent
							
								
									832622e6bd
								
							
						
					
					
						commit
						6103aa96ec
					
				
					 3 changed files with 47 additions and 2 deletions
				
			
		| 
						 | 
				
			
			@ -712,6 +712,7 @@ bool bpf_helper_changes_pkt_data(void *func);
 | 
			
		|||
struct bpf_prog *bpf_patch_insn_single(struct bpf_prog *prog, u32 off,
 | 
			
		||||
				       const struct bpf_insn *patch, u32 len);
 | 
			
		||||
 | 
			
		||||
int xdp_do_generic_redirect(struct net_device *dev, struct sk_buff *skb);
 | 
			
		||||
int xdp_do_redirect(struct net_device *dev, struct xdp_buff *xdp);
 | 
			
		||||
 | 
			
		||||
void bpf_warn_invalid_xdp_action(u32 act);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3902,6 +3902,7 @@ static u32 netif_receive_generic_xdp(struct sk_buff *skb,
 | 
			
		|||
		__skb_push(skb, -off);
 | 
			
		||||
 | 
			
		||||
	switch (act) {
 | 
			
		||||
	case XDP_REDIRECT:
 | 
			
		||||
	case XDP_TX:
 | 
			
		||||
		__skb_push(skb, mac_len);
 | 
			
		||||
		/* fall through */
 | 
			
		||||
| 
						 | 
				
			
			@ -3956,14 +3957,27 @@ static int do_xdp_generic(struct sk_buff *skb)
 | 
			
		|||
 | 
			
		||||
	if (xdp_prog) {
 | 
			
		||||
		u32 act = netif_receive_generic_xdp(skb, xdp_prog);
 | 
			
		||||
		int err;
 | 
			
		||||
 | 
			
		||||
		if (act != XDP_PASS) {
 | 
			
		||||
			if (act == XDP_TX)
 | 
			
		||||
			switch (act) {
 | 
			
		||||
			case XDP_REDIRECT:
 | 
			
		||||
				err = xdp_do_generic_redirect(skb->dev, skb);
 | 
			
		||||
				if (err)
 | 
			
		||||
					goto out_redir;
 | 
			
		||||
			/* fallthru to submit skb */
 | 
			
		||||
			case XDP_TX:
 | 
			
		||||
				generic_xdp_tx(skb, xdp_prog);
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
			return XDP_DROP;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return XDP_PASS;
 | 
			
		||||
out_redir:
 | 
			
		||||
	trace_xdp_exception(skb->dev, xdp_prog, XDP_REDIRECT);
 | 
			
		||||
	kfree_skb(skb);
 | 
			
		||||
	return XDP_DROP;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int netif_rx_internal(struct sk_buff *skb)
 | 
			
		||||
| 
						 | 
				
			
			@ -3977,8 +3991,12 @@ static int netif_rx_internal(struct sk_buff *skb)
 | 
			
		|||
	if (static_key_false(&generic_xdp_needed)) {
 | 
			
		||||
		int ret = do_xdp_generic(skb);
 | 
			
		||||
 | 
			
		||||
		/* Consider XDP consuming the packet a success from
 | 
			
		||||
		 * the netdev point of view we do not want to count
 | 
			
		||||
		 * this as an error.
 | 
			
		||||
		 */
 | 
			
		||||
		if (ret != XDP_PASS)
 | 
			
		||||
			return NET_RX_DROP;
 | 
			
		||||
			return NET_RX_SUCCESS;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_RPS
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2437,6 +2437,32 @@ int xdp_do_redirect(struct net_device *dev, struct xdp_buff *xdp)
 | 
			
		|||
}
 | 
			
		||||
EXPORT_SYMBOL_GPL(xdp_do_redirect);
 | 
			
		||||
 | 
			
		||||
int xdp_do_generic_redirect(struct net_device *dev, struct sk_buff *skb)
 | 
			
		||||
{
 | 
			
		||||
	struct redirect_info *ri = this_cpu_ptr(&redirect_info);
 | 
			
		||||
	unsigned int len;
 | 
			
		||||
 | 
			
		||||
	dev = dev_get_by_index_rcu(dev_net(dev), ri->ifindex);
 | 
			
		||||
	ri->ifindex = 0;
 | 
			
		||||
	if (unlikely(!dev)) {
 | 
			
		||||
		bpf_warn_invalid_xdp_redirect(ri->ifindex);
 | 
			
		||||
		goto err;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (unlikely(!(dev->flags & IFF_UP)))
 | 
			
		||||
		goto err;
 | 
			
		||||
 | 
			
		||||
	len = dev->mtu + dev->hard_header_len + VLAN_HLEN;
 | 
			
		||||
	if (skb->len > len)
 | 
			
		||||
		goto err;
 | 
			
		||||
 | 
			
		||||
	skb->dev = dev;
 | 
			
		||||
	return 0;
 | 
			
		||||
err:
 | 
			
		||||
	return -EINVAL;
 | 
			
		||||
}
 | 
			
		||||
EXPORT_SYMBOL_GPL(xdp_do_generic_redirect);
 | 
			
		||||
 | 
			
		||||
BPF_CALL_2(bpf_xdp_redirect, u32, ifindex, u64, flags)
 | 
			
		||||
{
 | 
			
		||||
	struct redirect_info *ri = this_cpu_ptr(&redirect_info);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue