[llvm-dev] bpf compilation using clang
Sameeh Jubran via llvm-dev
llvm-dev at lists.llvm.org
Tue Sep 25 03:48:24 PDT 2018
The headers can be found here:
iproute2$ git remote -v
origin https://git.kernel.org/pub/scm/network/iproute2/iproute2.git/ (fetch)
origin https://git.kernel.org/pub/scm/network/iproute2/iproute2.git/ (push)
I have more headers which I have created. I can push this to github if
needed and you'll have all of the dependencies.
iteration count of 40 is the max key size.
I have mistakenly sent the wrong source code. This is the up-to-date one:
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <asm/types.h>
#include <linux/in.h>
#include <linux/if.h>
#include <linux/if_ether.h>
#include <linux/ip.h>
#include <linux/ipv6.h>
#include <linux/if_tunnel.h>
#include <linux/filter.h>
#include <linux/bpf.h>
#include "bpf_api.h"
#include "rss_tap_bpf.h"
/** Create IPv4 address */
#define IPv4(a, b, c, d) ((__u32)(((a) & 0xff) << 24) | \
(((b) & 0xff) << 16) | \
(((c) & 0xff) << 8) | \
((d) & 0xff))
#define PORT(a, b) ((__u16)(((a) & 0xff) << 8) | \
((b) & 0xff))
#define KEY_IDX 0
struct vlan_hdr {
__be16 h_vlan_TCI;
__be16 h_vlan_encapsulated_proto;
};
//struct bpf_elf_map __attribute__((section("maps"), used))
struct bpf_elf_map __attribute__((section("maps"), used)) map_rss = {
.type = BPF_MAP_TYPE_ARRAY,
.size_key = sizeof(__u32),
.size_value = sizeof(struct rss_key),
.max_elem = 1,
};
//struct bpf_elf_map __attribute__((section("maps"), used))
struct bpf_elf_map __attribute__((section("maps"), used)) map_rss_key = {
.type = BPF_MAP_TYPE_ARRAY,
.size_key = sizeof(__u32),
.size_value = sizeof(__u8),
.max_elem = RSS_MAX_KEY_SIZE,
};
//struct bpf_elf_map __attribute__((section("maps"), used))
struct bpf_elf_map __attribute__((section("maps"), used))
map_rss_indirection = {
.type = BPF_MAP_TYPE_ARRAY,
.size_key = sizeof(__u32),
.size_value = sizeof(__u32),
.max_elem = RSS_MAX_INDIRECTION_SIZE,
};
struct ipv4_l3_l4_tuple {
__u32 src_addr;
__u32 dst_addr;
__u16 dport;
__u16 sport;
} __attribute__((packed));
struct ipv6_l3_l4_tuple {
__u8 src_addr[16];
__u8 dst_addr[16];
__u16 dport;
__u16 sport;
} __attribute__((packed));
static __u32 __attribute__((always_inline))
rte_softrss_be(const __u32 *input_tuple, const __u8 *key,
__u8 input_len)
{
__u32 i, j, hash = 0;
#pragma unroll
for (j = 0; j < input_len; j++) {
#pragma unroll
for (i = 0; i < 32; i++) {
if (input_tuple[j] & (1 << (31 - i))) {
hash ^= ((const __u32 *) key)[j] << i |
(__u32)((uint64_t)
(((const __u32 *) key)[j + 1])
>> (32 - i));
}
}
}
return hash;
}
static void __attribute__((always_inline))
fill_key_to_array(__u8 *array)
{
__u32 i = 0;
__u8 *elem;
for(i = 0; i < RSS_MAX_KEY_SIZE; i++)
{
elem = map_lookup_elem(&map_rss_key, &i);
array[i] = elem == NULL ? '0' : *elem;
}
}
static int __attribute__((always_inline))
rss_l3_l4(struct __sk_buff *skb)
{
__u64 proto = load_half(skb, 12);
__u64 nhoff = ETH_HLEN;
__u32 key_idx = 0xdeadbeef;
__u32 hash = 0;
int j = 0;
__u32 * queue;
__u8 key[RSS_MAX_KEY_SIZE];
struct rss_key *rss_key;
rss_key = (struct rss_key *) map_lookup_elem(&map_rss, &key_idx);
if (!rss_key) {
return -1;
}
fill_key_to_array(key);
if (proto == ETH_P_8021AD) {
proto = load_half(skb, nhoff + offsetof(struct vlan_hdr,
h_vlan_encapsulated_proto));
nhoff += sizeof(struct vlan_hdr);
}
if (proto == ETH_P_8021Q) {
proto = load_half(skb, nhoff + offsetof(struct vlan_hdr,
h_vlan_encapsulated_proto));
nhoff += sizeof(struct vlan_hdr);
}
if (likely(proto == ETH_P_IP)) {
struct ipv4_l3_l4_tuple v4_tuple = {
.src_addr = IPv4(load_byte(skb, nhoff + offsetof(struct iphdr, saddr)),
load_byte(skb, nhoff + offsetof(struct iphdr, saddr) + 1),
load_byte(skb, nhoff + offsetof(struct iphdr, saddr) + 2),
load_byte(skb, nhoff + offsetof(struct iphdr, saddr) + 3)),
.dst_addr = IPv4(load_byte(skb, nhoff + offsetof(struct iphdr, daddr)),
load_byte(skb, nhoff + offsetof(struct iphdr, daddr) + 1),
load_byte(skb, nhoff + offsetof(struct iphdr, daddr) + 2),
load_byte(skb, nhoff + offsetof(struct iphdr, daddr) + 3)),
.sport = PORT(load_byte(skb, nhoff + sizeof(struct iphdr)),
load_byte(skb, nhoff + sizeof(struct iphdr) + 1)),
.dport = PORT(load_byte(skb, nhoff + sizeof(struct iphdr) + 2),
load_byte(skb, nhoff + sizeof(struct iphdr) + 3))
};
__u8 input_len = sizeof(v4_tuple) / sizeof(__u32);
if (rss_key->hash_fields & (1 << HASH_FIELD_IPV4_L3))
input_len--;
hash = rte_softrss_be((__u32 *)&v4_tuple, key, 3);
} else if (proto == htons(ETH_P_IPV6)) {
struct ipv6_l3_l4_tuple v6_tuple;
for (j = 0; j < 4; j++)
*((uint32_t *)&v6_tuple.src_addr + j) =
load_word(skb, nhoff + offsetof(struct ipv6hdr, saddr) + j);
for (j = 0; j < 4; j++)
*((uint32_t *)&v6_tuple.dst_addr + j) =
load_word(skb, nhoff + offsetof(struct ipv6hdr, daddr) + j);
v6_tuple.sport = PORT(load_byte(skb, nhoff + sizeof(struct ipv6hdr)),
load_byte(skb, nhoff + sizeof(struct ipv6hdr) + 1));
v6_tuple.dport = PORT(load_byte(skb, nhoff + sizeof(struct ipv6hdr) + 2),
load_byte(skb, nhoff + sizeof(struct ipv6hdr) + 3));
__u8 input_len = sizeof(v6_tuple) / sizeof(__u32);
if (rss_key->hash_fields & (1 << HASH_FIELD_IPV6_L3))
input_len--;
hash = rte_softrss_be((__u32 *)&v6_tuple, key, 9);
} else {
return -1;
}
__u32 indirection_index = hash % rss_key->nb_queues;
queue = (__u32 *) map_lookup_elem(&map_rss_indirection, &indirection_index);
return queue == NULL ? -1 : (int) *queue;
}
#define RSS(L) \
__section(#L) int \
L ## _hash(struct __sk_buff *skb) \
{ \
return rss_ ## L(skb); \
}
RSS(l3_l4)
BPF_LICENSE("Dual BSD/GPL");On Tue, Sep 25, 2018 at 1:21 PM Tim
Northover <t.p.northover at gmail.com> wrote:
>
> On Tue, 25 Sep 2018 at 09:27, Sameeh Jubran <sameeh at daynix.com> wrote:
> > * Here you can find the source code:
>
> I'm afraid I don't have the headers to compile it myself, and couldn't
> track them down easily. The preprocessed output (with -E as well)
> would be more useful (as an attachment).
>
> At the moment I can't really link that loop back to anything in the
> source. It seems to have an iteration count of 40 which doesn't match
> with anything I can see.
>
> Cheers.
>
> Tim.
--
Respectfully,
Sameeh Jubran
Linkedin
Software Engineer @ Daynix.
More information about the llvm-dev
mailing list