|
48 | 48 | #include <linux/bpf.h> |
49 | 49 | #include <net/sch_generic.h> |
50 | 50 | #include <net/cls_cgroup.h> |
| 51 | +#include <net/dst_metadata.h> |
51 | 52 |
|
52 | 53 | /** |
53 | 54 | * sk_filter - run a packet through a socket filter |
@@ -1483,6 +1484,78 @@ bool bpf_helper_changes_skb_data(void *func) |
1483 | 1484 | return false; |
1484 | 1485 | } |
1485 | 1486 |
|
| 1487 | +static u64 bpf_skb_get_tunnel_key(u64 r1, u64 r2, u64 size, u64 flags, u64 r5) |
| 1488 | +{ |
| 1489 | + struct sk_buff *skb = (struct sk_buff *) (long) r1; |
| 1490 | + struct bpf_tunnel_key *to = (struct bpf_tunnel_key *) (long) r2; |
| 1491 | + struct ip_tunnel_info *info = skb_tunnel_info(skb, AF_INET); |
| 1492 | + |
| 1493 | + if (unlikely(size != sizeof(struct bpf_tunnel_key) || flags || !info)) |
| 1494 | + return -EINVAL; |
| 1495 | + |
| 1496 | + to->tunnel_id = be64_to_cpu(info->key.tun_id); |
| 1497 | + to->remote_ipv4 = be32_to_cpu(info->key.ipv4_src); |
| 1498 | + |
| 1499 | + return 0; |
| 1500 | +} |
| 1501 | + |
| 1502 | +const struct bpf_func_proto bpf_skb_get_tunnel_key_proto = { |
| 1503 | + .func = bpf_skb_get_tunnel_key, |
| 1504 | + .gpl_only = false, |
| 1505 | + .ret_type = RET_INTEGER, |
| 1506 | + .arg1_type = ARG_PTR_TO_CTX, |
| 1507 | + .arg2_type = ARG_PTR_TO_STACK, |
| 1508 | + .arg3_type = ARG_CONST_STACK_SIZE, |
| 1509 | + .arg4_type = ARG_ANYTHING, |
| 1510 | +}; |
| 1511 | + |
| 1512 | +static struct metadata_dst __percpu *md_dst; |
| 1513 | + |
| 1514 | +static u64 bpf_skb_set_tunnel_key(u64 r1, u64 r2, u64 size, u64 flags, u64 r5) |
| 1515 | +{ |
| 1516 | + struct sk_buff *skb = (struct sk_buff *) (long) r1; |
| 1517 | + struct bpf_tunnel_key *from = (struct bpf_tunnel_key *) (long) r2; |
| 1518 | + struct metadata_dst *md = this_cpu_ptr(md_dst); |
| 1519 | + struct ip_tunnel_info *info; |
| 1520 | + |
| 1521 | + if (unlikely(size != sizeof(struct bpf_tunnel_key) || flags)) |
| 1522 | + return -EINVAL; |
| 1523 | + |
| 1524 | + skb_dst_drop(skb); |
| 1525 | + dst_hold((struct dst_entry *) md); |
| 1526 | + skb_dst_set(skb, (struct dst_entry *) md); |
| 1527 | + |
| 1528 | + info = &md->u.tun_info; |
| 1529 | + info->mode = IP_TUNNEL_INFO_TX; |
| 1530 | + info->key.tun_id = cpu_to_be64(from->tunnel_id); |
| 1531 | + info->key.ipv4_dst = cpu_to_be32(from->remote_ipv4); |
| 1532 | + |
| 1533 | + return 0; |
| 1534 | +} |
| 1535 | + |
| 1536 | +const struct bpf_func_proto bpf_skb_set_tunnel_key_proto = { |
| 1537 | + .func = bpf_skb_set_tunnel_key, |
| 1538 | + .gpl_only = false, |
| 1539 | + .ret_type = RET_INTEGER, |
| 1540 | + .arg1_type = ARG_PTR_TO_CTX, |
| 1541 | + .arg2_type = ARG_PTR_TO_STACK, |
| 1542 | + .arg3_type = ARG_CONST_STACK_SIZE, |
| 1543 | + .arg4_type = ARG_ANYTHING, |
| 1544 | +}; |
| 1545 | + |
| 1546 | +static const struct bpf_func_proto *bpf_get_skb_set_tunnel_key_proto(void) |
| 1547 | +{ |
| 1548 | + if (!md_dst) { |
| 1549 | + /* race is not possible, since it's called from |
| 1550 | + * verifier that is holding verifier mutex |
| 1551 | + */ |
| 1552 | + md_dst = metadata_dst_alloc_percpu(0, GFP_KERNEL); |
| 1553 | + if (!md_dst) |
| 1554 | + return NULL; |
| 1555 | + } |
| 1556 | + return &bpf_skb_set_tunnel_key_proto; |
| 1557 | +} |
| 1558 | + |
1486 | 1559 | static const struct bpf_func_proto * |
1487 | 1560 | sk_filter_func_proto(enum bpf_func_id func_id) |
1488 | 1561 | { |
@@ -1526,6 +1599,10 @@ tc_cls_act_func_proto(enum bpf_func_id func_id) |
1526 | 1599 | return &bpf_skb_vlan_push_proto; |
1527 | 1600 | case BPF_FUNC_skb_vlan_pop: |
1528 | 1601 | return &bpf_skb_vlan_pop_proto; |
| 1602 | + case BPF_FUNC_skb_get_tunnel_key: |
| 1603 | + return &bpf_skb_get_tunnel_key_proto; |
| 1604 | + case BPF_FUNC_skb_set_tunnel_key: |
| 1605 | + return bpf_get_skb_set_tunnel_key_proto(); |
1529 | 1606 | default: |
1530 | 1607 | return sk_filter_func_proto(func_id); |
1531 | 1608 | } |
|
0 commit comments