diff --git a/traffic-pacing-edt/xdp_cpumap_loader.c b/traffic-pacing-edt/xdp_cpumap_loader.c index fb6f08b..3a954b9 100644 --- a/traffic-pacing-edt/xdp_cpumap_loader.c +++ b/traffic-pacing-edt/xdp_cpumap_loader.c @@ -78,7 +78,7 @@ static int create_cpu_entry(int cpumap_fd, __u32 cpu, err = bpf_map_update_elem(cpumap_fd, &cpu, value, 0); if (err) { fprintf(stderr, "Create CPU entry failed (err:%d)\n", err); - exit(EXIT_FAIL_BPF); + return EXIT_FAIL_BPF; } return 0; diff --git a/traffic-pacing-edt/xdp_cpumap_qinq.c b/traffic-pacing-edt/xdp_cpumap_qinq.c index 1fc98b0..5803c95 100644 --- a/traffic-pacing-edt/xdp_cpumap_qinq.c +++ b/traffic-pacing-edt/xdp_cpumap_qinq.c @@ -12,6 +12,9 @@ #define MAX_CPUS 24 +/* This global variable is used for limiting CPU that can be selected */ +__u32 global_max_cpus = 12; /* TODO: Allow userspace to adjust this */ + /* Special map type that can XDP_REDIRECT frames to another CPU */ struct { __uint(type, BPF_MAP_TYPE_CPUMAP); @@ -20,6 +23,22 @@ struct { __uint(max_entries, MAX_CPUS); } cpumap SEC(".maps"); +static __always_inline +__u16 extract_vlan_key(struct collect_vlans *vlans) +{ + __u16 vlan_key = 0; + + if (vlans->id[1]) { + /* Inner Q-in-Q VLAN present use that as key */ + vlan_key = vlans->id[1]; + } else { + /* If only one VLAN tag, use it as key */ + vlan_key = vlans->id[0]; + } + + return vlan_key; +} + SEC("xdp") int xdp_cpumap_qinq(struct xdp_md *ctx) { @@ -53,7 +72,10 @@ int xdp_cpumap_qinq(struct xdp_md *ctx) goto out; } - // WARNING: Userspace MUST insert entries into cpumap + /* Use inner VLAN as key and hash based on max_cpus */ + cpu_dest = extract_vlan_key(&vlans) % global_max_cpus; + + /* Notice: Userspace MUST insert entries into cpumap */ action = bpf_redirect_map(&cpumap, cpu_dest, XDP_PASS); out: return action;