aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWillem de Bruijn <willemb@google.com>2015-08-14 22:31:35 -0400
committerDavid S. Miller <davem@davemloft.net>2015-08-17 17:22:48 -0400
commitf2e520956a1ab636698f8160194c9b8ac0989aab (patch)
treef3ff84457be59fab5303f64b5e5ba93204c3f90b
parent47dceb8ecdc1c3ad1818dfea3d659a05b74c3fc2 (diff)
packet: add extended BPF fanout mode
Add fanout mode PACKET_FANOUT_EBPF that accepts an en extended BPF program to select a socket. Update the internal eBPF program by passing to socket option SOL_PACKET/PACKET_FANOUT_DATA a file descriptor returned by bpf(). Signed-off-by: Willem de Bruijn <willemb@google.com> Acked-by: Alexei Starovoitov <ast@plumgrid.com> Acked-by: Daniel Borkmann <daniel@iogearbox.net> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/uapi/linux/if_packet.h1
-rw-r--r--net/packet/af_packet.c31
2 files changed, 32 insertions, 0 deletions
diff --git a/include/uapi/linux/if_packet.h b/include/uapi/linux/if_packet.h
index a4bb16fa822e..9e7edfd8141e 100644
--- a/include/uapi/linux/if_packet.h
+++ b/include/uapi/linux/if_packet.h
@@ -64,6 +64,7 @@ struct sockaddr_ll {
64#define PACKET_FANOUT_RND 4 64#define PACKET_FANOUT_RND 4
65#define PACKET_FANOUT_QM 5 65#define PACKET_FANOUT_QM 5
66#define PACKET_FANOUT_CBPF 6 66#define PACKET_FANOUT_CBPF 6
67#define PACKET_FANOUT_EBPF 7
67#define PACKET_FANOUT_FLAG_ROLLOVER 0x1000 68#define PACKET_FANOUT_FLAG_ROLLOVER 0x1000
68#define PACKET_FANOUT_FLAG_DEFRAG 0x8000 69#define PACKET_FANOUT_FLAG_DEFRAG 0x8000
69 70
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 8869d07013e6..7b8e39a22387 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -1472,6 +1472,7 @@ static int packet_rcv_fanout(struct sk_buff *skb, struct net_device *dev,
1472 idx = fanout_demux_rollover(f, skb, 0, false, num); 1472 idx = fanout_demux_rollover(f, skb, 0, false, num);
1473 break; 1473 break;
1474 case PACKET_FANOUT_CBPF: 1474 case PACKET_FANOUT_CBPF:
1475 case PACKET_FANOUT_EBPF:
1475 idx = fanout_demux_bpf(f, skb, num); 1476 idx = fanout_demux_bpf(f, skb, num);
1476 break; 1477 break;
1477 } 1478 }
@@ -1529,6 +1530,7 @@ static void fanout_init_data(struct packet_fanout *f)
1529 atomic_set(&f->rr_cur, 0); 1530 atomic_set(&f->rr_cur, 0);
1530 break; 1531 break;
1531 case PACKET_FANOUT_CBPF: 1532 case PACKET_FANOUT_CBPF:
1533 case PACKET_FANOUT_EBPF:
1532 RCU_INIT_POINTER(f->bpf_prog, NULL); 1534 RCU_INIT_POINTER(f->bpf_prog, NULL);
1533 break; 1535 break;
1534 } 1536 }
@@ -1571,12 +1573,39 @@ static int fanout_set_data_cbpf(struct packet_sock *po, char __user *data,
1571 return 0; 1573 return 0;
1572} 1574}
1573 1575
1576static int fanout_set_data_ebpf(struct packet_sock *po, char __user *data,
1577 unsigned int len)
1578{
1579 struct bpf_prog *new;
1580 u32 fd;
1581
1582 if (sock_flag(&po->sk, SOCK_FILTER_LOCKED))
1583 return -EPERM;
1584 if (len != sizeof(fd))
1585 return -EINVAL;
1586 if (copy_from_user(&fd, data, len))
1587 return -EFAULT;
1588
1589 new = bpf_prog_get(fd);
1590 if (IS_ERR(new))
1591 return PTR_ERR(new);
1592 if (new->type != BPF_PROG_TYPE_SOCKET_FILTER) {
1593 bpf_prog_put(new);
1594 return -EINVAL;
1595 }
1596
1597 __fanout_set_data_bpf(po->fanout, new);
1598 return 0;
1599}
1600
1574static int fanout_set_data(struct packet_sock *po, char __user *data, 1601static int fanout_set_data(struct packet_sock *po, char __user *data,
1575 unsigned int len) 1602 unsigned int len)
1576{ 1603{
1577 switch (po->fanout->type) { 1604 switch (po->fanout->type) {
1578 case PACKET_FANOUT_CBPF: 1605 case PACKET_FANOUT_CBPF:
1579 return fanout_set_data_cbpf(po, data, len); 1606 return fanout_set_data_cbpf(po, data, len);
1607 case PACKET_FANOUT_EBPF:
1608 return fanout_set_data_ebpf(po, data, len);
1580 default: 1609 default:
1581 return -EINVAL; 1610 return -EINVAL;
1582 }; 1611 };
@@ -1586,6 +1615,7 @@ static void fanout_release_data(struct packet_fanout *f)
1586{ 1615{
1587 switch (f->type) { 1616 switch (f->type) {
1588 case PACKET_FANOUT_CBPF: 1617 case PACKET_FANOUT_CBPF:
1618 case PACKET_FANOUT_EBPF:
1589 __fanout_set_data_bpf(f, NULL); 1619 __fanout_set_data_bpf(f, NULL);
1590 }; 1620 };
1591} 1621}
@@ -1608,6 +1638,7 @@ static int fanout_add(struct sock *sk, u16 id, u16 type_flags)
1608 case PACKET_FANOUT_RND: 1638 case PACKET_FANOUT_RND:
1609 case PACKET_FANOUT_QM: 1639 case PACKET_FANOUT_QM:
1610 case PACKET_FANOUT_CBPF: 1640 case PACKET_FANOUT_CBPF:
1641 case PACKET_FANOUT_EBPF:
1611 break; 1642 break;
1612 default: 1643 default:
1613 return -EINVAL; 1644 return -EINVAL;