Commit cc050954 authored by Franck Messaoudi's avatar Franck Messaoudi

refacotr: refactoring the code and starting the qos implementation

parent ad060df5
......@@ -289,6 +289,7 @@ include_directories(${SRC_TOP_DIR}/pfcp)
include_directories(${SRC_TOP_DIR}/udp)
include_directories(${SRC_TOP_DIR}/upf_app)
include_directories(${SRC_TOP_DIR}/upf_app/bpf)
include_directories(${SRC_TOP_DIR}/upf_app/bpf/rules/include)
include_directories(${SRC_TOP_DIR}/upf_app/app)
include_directories(${SRC_TOP_DIR}/upf_app/interfaces)
include_directories(${SRC_TOP_DIR}/upf_app/simpleswitch)
......
......@@ -15,6 +15,14 @@ include(${SRC_TOP_DIR}/${MOUNTED_COMMON}/utils/utils.cmake)
include(${SRC_TOP_DIR}/${MOUNTED_COMMON}/model/nrf/nrf_model.cmake)
include_directories(${SRC_TOP_DIR}/upf_app/bpf)
include_directories(${SRC_TOP_DIR}/upf_app/bpf/rules/include)
include_directories(${SRC_TOP_DIR}/upf_app/bpf/rules/pdr)
include_directories(${SRC_TOP_DIR}/upf_app/bpf/rules/far)
include_directories(${SRC_TOP_DIR}/upf_app/bpf/rules/qer)
#include_directories(${SRC_TOP_DIR}/upf_app/bpf/rules/urr)
#include_directories(${SRC_TOP_DIR}/upf_app/bpf/rules/bar)
#include_directories(${SRC_TOP_DIR}/upf_app/bpf/rules/mar)
include_directories(${SRC_TOP_DIR}/upf_app/app)
set(GTP_INTERFACE $ENV{GTP_INTERFACE})
......
......@@ -15,9 +15,6 @@
#include "NextHopFinder.hpp"
#include <errno.h>
#include <arpa/inet.h>
//#include <traffic_classification.h>
// #include <ue_teid_qfi_matching.h>
#include <session_mapping.h>
#include <arp_table_maps.h>
#include "upf_config.hpp"
#include <thread>
......
include(${SRC_TOP_DIR}/upf_app/cmake/toolchain.cmake)
include_directories(${SRC_TOP_DIR}/upf_app)
include_directories(${SRC_TOP_DIR}/upf_app/bpf)
include_directories(${SRC_TOP_DIR}/upf_app/bpf/rules)
include_directories(${SRC_TOP_DIR}/upf_app/bpf/rules/include)
include_directories(${SRC_TOP_DIR}/upf_app/bpf/rules/pdr)
include_directories(${SRC_TOP_DIR}/upf_app/bpf/rules/far)
include_directories(${SRC_TOP_DIR}/upf_app/bpf/rules/qer)
#include_directories(${SRC_TOP_DIR}/upf_app/bpf/rules/urr)
#include_directories(${SRC_TOP_DIR}/upf_app/bpf/rules/bar)
#include_directories(${SRC_TOP_DIR}/upf_app/bpf/rules/mar)
include_directories(${SRC_TOP_DIR}/upf_app/include)
add_definitions(-DKERNEL_SPACE)
add_custom_target(upf_ebpf_xdp_all DEPENDS pfcp_session_lookup_ebpf_xdp pfcp_session_pdr_lookup_ebpf_xdp far_ebpf_xdp)
# function(bpf prefix)
# add_library(${prefix}_ebpf_xdp STATIC ${prefix}_ebpf_xdp_prgrm_kernel.c)
# add_custom_command(
# TARGET ${prefix}_ebpf_xdp
# PRE_LINK
# COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_SOURCE_DIR}/../skel
# COMMAND bpftool gen skeleton $<TARGET_OBJECTS:${prefix}_ebpf_xdp> > ${CMAKE_CURRENT_SOURCE_DIR}/../skel/${prefix}_ebpf_xdp_prgrm_kernel_skel.h
# COMMAND sed -i '9i\#define typeof\(x\) __typeof__\(x\)' ${CMAKE_CURRENT_SOURCE_DIR}/../skel/${prefix}_ebpf_xdp_prgrm_kernel_skel.h
# DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${prefix}_ebpf_xdp_prgrm_kernel.c
# )
# endfunction()
function(bpf prefix)
add_library(${prefix}_ebpf_xdp STATIC ${prefix}_ebpf_xdp_prgrm_kernel.c)
if (${prefix} STREQUAL "pfcp_session_lookup" OR ${prefix} STREQUAL "pfcp_session_pdr_lookup")
set(source_dir "${CMAKE_CURRENT_SOURCE_DIR}/rules/pdr")
elseif (${prefix} STREQUAL "far")
set(source_dir "${CMAKE_CURRENT_SOURCE_DIR}/rules/far")
else()
message(FATAL_ERROR "Invalid prefix: ${prefix}")
endif()
add_library(${prefix}_ebpf_xdp STATIC ${source_dir}/${prefix}_ebpf_xdp_prgrm_kernel.c)
add_custom_command(
TARGET ${prefix}_ebpf_xdp
PRE_LINK
COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_SOURCE_DIR}/../skel
COMMAND bpftool gen skeleton $<TARGET_OBJECTS:${prefix}_ebpf_xdp> > ${CMAKE_CURRENT_SOURCE_DIR}/../skel/${prefix}_ebpf_xdp_prgrm_kernel_skel.h
COMMAND sed -i '9i\#define typeof\(x\) __typeof__\(x\)' ${CMAKE_CURRENT_SOURCE_DIR}/../skel/${prefix}_ebpf_xdp_prgrm_kernel_skel.h
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${prefix}_ebpf_xdp_prgrm_kernel.c
DEPENDS ${source_dir}/${prefix}_ebpf_xdp_prgrm_kernel.c
)
endfunction()
bpf(pfcp_session_lookup)
bpf(pfcp_session_pdr_lookup)
bpf(far)
\ No newline at end of file
bpf(far)
In this implementation, the `qfi_classifier` function performs packet classification based on the destination port and stores the corresponding QFI in the packet data. The `token_bucket_filter` function implements the token bucket algorithm for traffic shaping and QoS enforcement based on the QFI and QER configuration.
To utilize this eBPF program with `tc` and `qdisc`, you would follow these steps:
1. Compile the eBPF program into an object file named `new_version.o`.
2. Use the `system()` function to execute the `tc` commands from within your C code to create the necessary qdisc and configure traffic shaping and packet classification rules.
3. Attach the compiled eBPF program to the qdisc using the `tc filter add` command.
Please note that the `tc` commands should be executed with appropriate privileges, typically as the root user or with `sudo`.
Remember to customize the QFI classification and QER configuration based on your specific requirements.
If you have any further questions, please let me know.
Apologies for the oversight. In the token_bucket_filter function, when the return value is TC_ACT_OK, it indicates that the packet should be allowed to pass through without any further modification. You can consider adding the appropriate tc command to continue processing the packet normally. Here's an updated version of the function to include the TC_ACT_OK handling:
-----------------------------------------
Let me explain how this code can be used with tc and qdisc.
Compile the eBPF program:
r
clang -O2 -target bpf -c qer_program.c -o qer_program.o
Load the eBPF program into the kernel:
bash
ip -force link set dev <interface> xdp obj qer_program.o
Replace <interface> with the name of the network interface where you want to apply the QER. For example, if you want to apply it to the eth0 interface, the command would be:
bash
ip -force link set dev eth0 xdp obj qer_program.o
Note that loading the eBPF program requires root privileges.
Configure traffic control rules using tc and qdisc:
csharp
tc qdisc add dev <interface> root handle 1: htb
tc class add dev <interface> parent 1: classid 1:1 htb rate <rate> burst <burst>
tc qdisc add dev <interface> parent 1:1 handle 10: sfq perturb 10
Replace <interface> with the name of the network interface where you applied the QER (same as in step 2). <rate> and <burst> are the desired rate and burst values for traffic shaping, respectively. Adjust these values according to your requirements.
Configure QER parameters using the qer_map:
c
struct qer_data qer_config = {
.qfi = 1, // Set the QFI for this QER configuration
.token_bucket_size = 1000000, // Set the token bucket size (in bytes)
.rate = 10000000, // Set the rate (in bps)
};
bpf_map_update_elem(&qer_map, &qer_config.qfi, &qer_config, BPF_ANY);
You can add multiple QER configurations by repeating the bpf_map_update_elem() call with different QFI values and corresponding QER parameters.
With the above steps, the eBPF program will classify packets based on their QFI using the qfi_classifier function. The token_bucket_filter function will then apply token bucket filtering based on the QER configurations and the token bucket map.
The traffic control rules defined with tc and qdisc will shape the traffic according to the configured rate and burst parameters.
Remember to replace <interface>, <rate>, and <burst> with the appropriate values for your network setup.
I hope this clarifies how the code can be used with tc and qdisc. Let me know if you have any further questions!
\ No newline at end of file
#include <stdlib.h>
int main() {
// Define the interface and QFI parameters
const char* interface = "eth0";
const int qfi1_classid = 1;
const int qfi2_classid = 2;
const int qfi1_rate = 1000000; // 1 Mbps
const int qfi2_rate = 2000000; // 2 Mbps
// Create the qdisc
char command[100];
sprintf(command, "tc qdisc add dev %s root handle 1: htb", interface);
system(command);
// Define classes for different QFIs
sprintf(
command, "tc class add dev %s parent 1: classid 1:%d htb rate %d",
interface, qfi1_classid, qfi1_rate);
system(command);
sprintf(
command, "tc class add dev %s parent 1: classid 1:%d htb rate %d",
interface, qfi2_classid, qfi2_rate);
system(command);
// Create filters to classify packets into respective QFIs
sprintf(
command,
"tc filter add dev %s parent 1: protocol ip prio 1 handle 1 fw classid "
"1:%d",
interface, qfi1_classid);
system(command);
sprintf(
command,
"tc filter add dev %s parent 1: protocol ip prio 1 handle 2 fw classid "
"1:%d",
interface, qfi2_classid);
system(command);
// Attach the eBPF program to the qdisc
sprintf(
command,
"tc filter add dev %s parent 1: bpf obj ebpf_program.o section "
"classifier flowid 1:1",
interface);
system(command);
// Configure token bucket filter for each QFI
sprintf(
command,
"tc qdisc add dev %s parent 1:%d handle 10: tbf rate %d burst 100000 "
"latency 50",
interface, qfi1_classid, qfi1_rate);
system(command);
sprintf(
command,
"tc qdisc add dev %s parent 1:%d handle 20: tbf rate %d burst 100000 "
"latency 50",
interface, qfi2_classid, qfi2_rate);
system(command);
return 0;
}
#include <linux/bpf.h>
#include <linux/pkt_cls.h>
#include <linux/if_ether.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#include <bpf_helpers.h>
#include <types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <linux/filter.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <linux/if_link.h>
struct qfi_data {
__u32 qfi;
};
struct bpf_map_def SEC("maps") qfi_map = {
.type = BPF_MAP_TYPE_HASH,
.key_size = sizeof(__u32),
.value_size = sizeof(struct qfi_data),
.max_entries = 1024,
};
struct qer_data {
__u32 qfi;
__u64 token_bucket_size;
__u64 rate;
};
struct bpf_map_def SEC("maps") qer_map = {
.type = BPF_MAP_TYPE_HASH,
.key_size = sizeof(__u32),
.value_size = sizeof(struct qer_data),
.max_entries = 1024,
};
struct bpf_map_def SEC("maps") token_bucket_map = {
.type = BPF_MAP_TYPE_HASH,
.key_size = sizeof(__u32),
.value_size = sizeof(__u64),
.max_entries = 1024,
};
SEC("classifier")
int qfi_classifier(struct __sk_buff* skb) {
// Extract Ethernet header
struct ethhdr* eth = bpf_hdr_pointer(skb);
// Filter IP packets
if (eth->h_proto != __constant_htons(ETH_P_IP)) return TC_ACT_OK;
// Extract IP header
struct iphdr* ip = (struct iphdr*) (eth + 1);
// Filter TCP packets
if (ip->protocol != IPPROTO_TCP) return TC_ACT_OK;
// Extract TCP header
struct tcphdr* tcp = (struct tcphdr*) (ip + 1);
// Classify packets based on destination port
__u32 qfi;
if (tcp->dest == __constant_htons(80)) {
qfi = 1;
} else if (tcp->dest == __constant_htons(443)) {
qfi = 2;
} else {
qfi = 0;
}
// Store the QFI in the packet data
struct qfi_data qfi_data = {
.qfi = qfi,
};
bpf_map_update_elem(&qfi_map, &qfi, &qfi_data, BPF_ANY);
// Store the QFI in the packet data
struct qfi_data* qfi_data = bpf_map_lookup_elem(&qfi_map, &qfi);
if (!qfi_data) {
// QFI not configured, drop the packet
return TC_ACT_SHOT;
}
skb->cb[0] = qfi_data->qfi;
return TC_ACT_OK;
}
SEC("traffic_shape")
int token_bucket_filter(struct __sk_buff* skb) {
// Retrieve the QFI from the packet data
__u32 qfi = (__u32) skb->cb[0];
// Retrieve QER data based on QFI
struct qer_data* qer = bpf_map_lookup_elem(&qer_map, &qfi);
if (!qer) {
// QER not configured for the QFI, allow the packet
return TC_ACT_OK;
}
// Retrieve token bucket for the QFI
__u64* tokens = bpf_map_lookup_elem(&token_bucket_map, &qfi);
if (!tokens) {
// Token bucket not initialized, allow the packet
return TC_ACT_OK;
}
// Calculate tokens based on rate
__u64 elapsed_time = bpf_ktime_get_ns() / 1000 - qer->token_bucket_size;
__u64 tokens_per_sec =
qer->rate / 1000000; // Convert rate from bps to tokens per microsecond
__u64 elapsed_tokens = elapsed_time * tokens_per_sec;
// Refill token bucket
*tokens = *tokens + elapsed_tokens;
if (*tokens > qer->token_bucket_size) {
*tokens = qer->token_bucket_size;
}
// Consume tokens for the packet
__u64 packet_size = (__u64) skb->len;
if (packet_size > *tokens) {
// Insufficient tokens, drop the packet
return TC_ACT_SHOT;
}
*tokens = *tokens - packet_size;
return TC_ACT_OK;
}
SEC("traffic_shape")
int token_bucket_filter(struct __sk_buff* skb) {
// Extract Ethernet header
struct ethhdr* eth = bpf_hdr_pointer(skb);
// Filter IP packets
if (eth->h_proto != __constant_htons(ETH_P_IP)) return TC_ACT_OK;
// Extract IP header
struct iphdr* ip = (struct iphdr*) (eth + 1);
// Filter TCP packets
if (ip->protocol != IPPROTO_TCP) return TC_ACT_OK;
// Extract TCP header
struct tcphdr* tcp = (struct tcphdr*) (ip + 1);
// Extract QFI from the IP header
__u8 qfi = (__u8) (ip->tos & 0x3F);
// Retrieve QER data based on QFI
struct qer_data* qer = bpf_map_lookup_elem(&qer_map, &qfi);
if (!qer) {
// QER not configured for the QFI, allow the packet
return TC_ACT_OK;
}
// Retrieve token bucket for the QFI
__u64* tokens = bpf_map_lookup_elem(&token_bucket_map, &qfi);
if (!tokens) {
// Token bucket not initialized, allow the packet
return TC_ACT_OK;
}
// Calculate tokens based on rate
__u64 elapsed_time = bpf_ktime_get_ns() / 1000 - qer->token_bucket_size;
__u64 new_tokens = elapsed_time * qer->rate / 1000000;
if (new_tokens > qer->token_bucket_size) {
new_tokens = qer->token_bucket_size;
}
qer->token_bucket_size = new_tokens;
if (*tokens >= skb->len) {
// Sufficient tokens available, consume tokens and allow the packet
*tokens -= skb->len;
return TC_ACT_OK;
} else {
// Insufficient tokens, drop the packet
return TC_ACT_SHOT;
}
}
\ No newline at end of file
#include <bpf_helpers.h>
#include <linux/bpf.h>
#include <types.h>
#include <linux/if_ether.h>
#include <linux/ip.h>
#include <linux/tcp.h>
struct qoe_metrics {
__u32 source_ip;
__u32 destination_ip;
__u16 source_port;
__u16 destination_port;
__u32 sequence_number;
__u32 ack_number;
// Add more QoE metrics as needed
};
struct pfcp_session_request {
__u32 source_ip;
__u32 destination_ip;
__u16 source_port;
__u16 destination_port;
// Add more session request fields as needed
};
struct bpf_map_def SEC("maps") qoe_map = {
.type = BPF_MAP_TYPE_HASH,
.key_size = sizeof(__u32),
.value_size = sizeof(struct qoe_metrics),
.max_entries = 1024,
};
struct bpf_map_def SEC("maps") pfcp_map = {
.type = BPF_MAP_TYPE_HASH,
.key_size = sizeof(__u32),
.value_size = sizeof(struct pfcp_session_request),
.max_entries = 1024,
};
SEC("filter")
int qoe_pfcp_monitor(struct __sk_buff* skb) {
// Extract Ethernet header
struct ethhdr* eth = bpf_hdr_pointer(skb);
// Filter IP packets
if (eth->h_proto != __constant_htons(ETH_P_IP)) return XDP_PASS;
// Extract IP header
struct iphdr* ip = (struct iphdr*) (eth + 1);
// Filter TCP packets
if (ip->protocol != IPPROTO_TCP) return XDP_PASS;
// Extract TCP header
struct tcphdr* tcp = (struct tcphdr*) (ip + 1);
// Extract QFI from the IP header
__u8 qfi = (__u8) (ip->tos & 0x3F);
// Filter packets based on the QFI value
if (qfi == 5) {
// Extract QoE metrics
struct qoe_metrics metrics = {
.source_ip = ip->saddr,
.destination_ip = ip->daddr,
.source_port = tcp->source,
.destination_port = tcp->dest,
.sequence_number = tcp->seq,
.ack_number = tcp->ack_seq,
// Add more QoE metric extraction here
};
// Store QoE metrics in the map
__u32 key = bpf_get_smp_processor_id();
bpf_map_update_elem(&qoe_map, &key, &metrics, BPF_ANY);
}
// Check if it's a PFCP session request
if (tcp->dest == __constant_htons(8805)) {
struct pfcp_session_request request = {
.source_ip = ip->saddr,
.destination_ip = ip->daddr,
.source_port = tcp->source,
.destination_port = tcp->dest,
// Extract and store more session request fields as needed
};
// Store PFCP session request in the map
__u32 key = bpf_get_smp_processor_id();
bpf_map_update_elem(&pfcp_map, &key, &request, BPF_ANY);
}
return XDP_PASS;
}
\ No newline at end of file
#include <linux/bpf.h>
#include <linux/if_ether.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/pkt_cls.h>
#include <bpf_helpers.h>
#include <types.h>
struct qer_data {
__u32 qfi;
__u64 token_bucket_size;
__u64 rate;
};
struct bpf_map_def SEC("maps") qer_map = {
.type = BPF_MAP_TYPE_HASH,
.key_size = sizeof(__u32),
.value_size = sizeof(struct qer_data),
.max_entries = 1,
};
struct bpf_map_def SEC("maps") token_bucket_map = {
.type = BPF_MAP_TYPE_HASH,
.key_size = sizeof(__u32),
.value_size = sizeof(__u64),
.max_entries = 1024,
};
SEC("traffic_shape")
int token_bucket_filter(struct __sk_buff* skb) {
// Extract Ethernet header
struct ethhdr* eth = bpf_hdr_pointer(skb);
// Filter IP packets
if (eth->h_proto != __constant_htons(ETH_P_IP)) return TC_ACT_OK;
// Extract IP header
struct iphdr* ip = (struct iphdr*) (eth + 1);
// Filter TCP packets
if (ip->protocol != IPPROTO_TCP) return TC_ACT_OK;
// Extract TCP header
struct tcphdr* tcp = (struct tcphdr*) (ip + 1);
// Extract QFI from the IP header
__u8 qfi = (__u8) (ip->tos & 0x3F);
// Retrieve QER data based on QFI
struct qer_data* qer = bpf_map_lookup_elem(&qer_map, &qfi);
if (!qer) {
// QER not configured for the QFI, allow the packet
return TC_ACT_OK;
}
// Retrieve token bucket for the QFI
__u64* tokens = bpf_map_lookup_elem(&token_bucket_map, &qfi);
if (!tokens) {
// Token bucket not initialized, allow the packet
return TC_ACT_OK;
}
// Calculate tokens based on rate
__u64 elapsed_time = bpf_ktime_get_ns() / 1000 - qer->token_bucket_size;
__u64 new_tokens = elapsed_time * qer->rate / 1000000;
if (new_tokens > qer->token_bucket_size) {
new_tokens = qer->token_bucket_size;
}
qer->token_bucket_size = new_tokens;
if (*tokens >= skb->len) {
// Sufficient tokens available, consume tokens and allow the packet
*tokens -= skb->len;
return TC_ACT_OK;
} else {
// Insufficient tokens, drop the packet
return TC_ACT_SHOT;
}
}
\ No newline at end of file
#ifndef __QFI_FLOW_MAPPING_TABLE_H__
#define __QFI_FLOW_MAPPING_TABLE_H__
#include <types.h>
#include <stdint.h>
typedef enum { DELAY_CRITICAL_GBR, GBR, NON_GBR } e_resource_type;
struct s_qfi_parameters {
e_resource_type resource_type;
u8 qfi;
u32 qos;
};
#endif // __QFI_FLOW_MAPPING_TABLE_H__
\ No newline at end of file
......@@ -45,21 +45,6 @@ int xdp_redirect_gtpu(struct xdp_md* p_ctx) {
* @return 0 (Success), 1 (Fail).
*/
// static u32 update_dst_mac_address(struct iphdr* p_ip, struct ethhdr* p_eth) {
// void* p_mac_address;
// p_mac_address = bpf_map_lookup_elem(&m_arp_table, &p_ip->daddr);
// if (!p_mac_address) {
// bpf_debug("MAC Address NOT Found for IP addr: 0x%x", p_ip->daddr);
// return 1;
// }
// memcpy(p_eth->h_dest, p_mac_address, sizeof(p_eth->h_dest));
// return 0;
// }
static u32 update_dst_mac_address(u32 ip, struct ethhdr* p_eth) {
struct s_arp_mapping* map_table;
memset(&map_table, 0, sizeof(struct s_arp_mapping));
......@@ -349,101 +334,6 @@ static u32 pfcp_far_apply(struct xdp_md* p_ctx, pfcp_far_t_* p_far) {
}
}
/*****************************************************************************************************************/
// static u32 pfcp_far_apply(struct xdp_md *p_ctx, pfcp_far_t_ *p_far)
// {
// void *p_data = (void *)(long)p_ctx->data;
// void *p_data_end = (void *)(long)p_ctx->data_end;
// struct ethhdr *p_eth = p_data;
// void *p_mac_address;
// u8 dest_interface;
// u16 outer_header_creation;
// // TODO dupl
// // TODO nocp
// // TODO buff
// if((void *)(p_eth + 1) > p_data_end) {
// bpf_debug("Invalid pointer");
// return XDP_DROP;
// }
// // Check if it is a forward action.
// if(!p_far) {
// bpf_debug("Invalid FAR!");
// return XDP_DROP;
// }
// dest_interface =
// p_far->forwarding_parameters.destination_interface.interface_value;
// outer_header_creation =
// p_far->forwarding_parameters.outer_header_creation.outer_header_creation_description;
// // TODO: Reorder the if's
// if(p_far->apply_action.forw) {
// if(dest_interface == INTERFACE_VALUE_CORE) {
// // Redirect to data network.
// bpf_debug("Destination is to INTERFACE_VALUE_CORE");
// // Check Outer header creation - IPv4 or IPv6
// switch(outer_header_creation) {
// case OUTER_HEADER_CREATION_UDP_IPV4:
// bpf_debug("OUTER_HEADER_CREATION_UDP_IPV4");
// struct ethhdr *p_new_eth = p_data + GTP_ENCAPSULATED_SIZE;
// // Move eth header forward.
// if((void *)(p_new_eth + 1) > p_data_end) {
// return 1;
// }
// __builtin_memcpy(p_new_eth, p_eth, sizeof(*p_eth));
// // Update destination mac address.
// struct iphdr *p_ip = (void *)(p_new_eth + 1);
// if((void *)(p_ip + 1) > p_data_end) {
// return XDP_DROP;
// }
// if(update_dst_mac_address(p_ip, p_new_eth)) {
// return XDP_DROP;
// }
// // Adjust head to the right.
// bpf_xdp_adjust_head(p_ctx, GTP_ENCAPSULATED_SIZE);
// return bpf_redirect_map(&m_redirect_interfaces, UPLINK, 0);
// bpf_debug("OUTER_HEADER_CREATION_UDP_IPV4 REDIRECT FAILED");
// break;
// case OUTER_HEADER_CREATION_UDP_IPV6:
// bpf_debug("OUTER_HEADER_CREATION_UDP_IPV6");
// // TODO
// break;
// default:
// bpf_debug("In destination to CORE - Invalid option: %d",
// outer_header_creation);
// }
// } else if(dest_interface == INTERFACE_VALUE_ACCESS) {
// // Redirect to core network.
// bpf_debug("Destination is to INTERFACE_VALUE_ACCESS");
// switch(outer_header_creation) {
// case OUTER_HEADER_CREATION_GTPU_UDP_IPV4:
// bpf_debug("OUTER_HEADER_CREATION_GTPU_UDP_IPV4");
// create_outer_header_gtpu_ipv4(p_ctx, p_far);
// return bpf_redirect_map(&m_redirect_interfaces, DOWNLINK, 0);
// break;
// case OUTER_HEADER_CREATION_GTPU_UDP_IPV6:
// bpf_debug("OUTER_HEADER_CREATION_GTPU_UDP_IPV6");
// break;
// default:
// bpf_debug("In destination to ACCESS - Invalid option: %d",
// outer_header_creation);
// }
// }
// } else {
// bpf_debug("Forward action unset");
// }
// return XDP_PASS;
// }
/*****************************************************************************************************************/
SEC("xdp_far")
int far_entry_point(struct xdp_md* p_ctx) {
......
......@@ -10,6 +10,7 @@
#include <next_prog_rule_map.h>
#include <next_prog_rule_key.h>
#include "interfaces.h"
#include "session_id.h"
//#include "traffic_classification.h"
// #include "session_mapping.h"
// #include "ue_teid_qfi_matching.h"
......@@ -75,13 +76,21 @@ struct bpf_map_def SEC("maps") m_upf_interfaces = {
/*****************************************************************************************************************/
// struct bpf_map_def SEC("maps") m_session_mapping = {
// .type = BPF_MAP_TYPE_HASH,
// .key_size = sizeof(u32), // ue_ip_address
// .value_size = sizeof(u32), // teid_dl
// .max_entries = MAX_LENGTH,
// };
struct bpf_map_def SEC("maps") m_session_mapping = {
.type = BPF_MAP_TYPE_HASH,
.key_size = sizeof(u32), // ue_ip_address
.value_size = sizeof(u32), // teid_dl
.value_size = sizeof(struct session_id), // < teid_ul, teid_dl, seid >
.max_entries = MAX_LENGTH,
};
/*****************************************************************************************************************/
// struct bpf_map_def SEC("maps") m_traffic_classification = {
......
#ifndef __SESSION_MAPPING_H__
#define __SESSION_MAPPING_H__
#ifndef __SESSION_ID_H__
#define __SESSION_ID_H__
#include <types.h>
#include <stdint.h>
struct s_session_mapping {
u32 ue_ip_address;
struct session_id {
u32 teid_ul;
u32 teid_dl;
u32 seid;
};
#endif // __SESSION_MAPPING_H__
\ No newline at end of file
#endif // __SESSION_ID_H__
\ No newline at end of file
......@@ -64,15 +64,16 @@ static u32 tail_call_next_prog(
/*****************************************************************************************************************/
static u32 handle_downlink_traffic(struct xdp_md* p_ctx, u32 ue_ip_address) {
// u32* teid_dl = NULL;
struct session_id* session;
memset(&session, 0, sizeof(struct session_id));
session = bpf_map_lookup_elem(&m_session_mapping, &ue_ip_address);
u32* teid_dl = bpf_map_lookup_elem(&m_session_mapping, &ue_ip_address);
if (teid_dl) {
if (session) {
u32 teid_dl = session->teid_dl;
bpf_printk(
"TEID downlink: 0x%x was found for UE IP: 0x%x", ue_ip_address,
*teid_dl);
tail_call_next_prog(p_ctx, *teid_dl, INTERFACE_VALUE_CORE, ue_ip_address);
teid_dl);
tail_call_next_prog(p_ctx, teid_dl, INTERFACE_VALUE_CORE, ue_ip_address);
}
bpf_debug("BPF tail call was not executed!");
......
#ifndef __FILTER_KEY_H__
#define __FILTER_KEY_H__
#include <types.h>
struct filter_key {
u32 src_ip;
u32 dst_ip;
u8 protocol;
u8 dst_port;
};
#endif // __FILTER_KEY_H__
#ifndef __GTP_U_TUNNEL_KEY_H__
#define __GTP_U_TUNNEL_KEY_H__
#include <types.h>
struct gtp_u_tunnel {
u32 teid_ul;
u32 teid_dl;
};
#endif // __GTP_U_TUNNEL_KEY_H__
#ifndef __QER_MAPS_H__
#define __QER_MAPS_H__
#include <bpf_helpers.h>
#include <linux/bpf.h>
#include <types.h>
#include "gtp_u_tunnel_key.h"
#include "filter_key.h"
#include "qfi_values.h"
#define QFI_MAX_ENTRIES 5000
/*****************************************************************************************************************/
struct bpf_map_def SEC("maps") m_gtp_u_tunnel = {
.type = BPF_MAP_TYPE_HASH,
.key_size = sizeof(struct gtp_u_tunnel), // < teid_ul, teid_dl >
.value_size = sizeof(u32), // seid
.max_entries = QFI_MAX_ENTRIES,
};
/*****************************************************************************************************************/
struct bpf_map_def SEC("maps") m_filter = {
.type = BPF_MAP_TYPE_HASH,
.key_size = sizeof(struct filter_key),
.value_size = sizeof(e_qfi),
.max_entries = QFI_MAX_ENTRIES,
};
#endif // __QER_MAPS_H__
\ No newline at end of file
This diff is collapsed.
#ifndef __QFI_VALUES_H__
#define __QFI_VALUES_H__
#include <stdint.h>
typedef enum {
QFI0,
QFI1,
QFI2,
QFI3,
QFI4,
QFI5,
QFI6,
QFI7,
QFI8,
QFI9
} e_qfi;
#endif // __QFI_VALUES_H__
\ No newline at end of file
#ifndef __TRAFFIC_H__
#define __TRAFFIC_H__
#include <types.h>
#include <stdint.h>
// u16 dscp_dl_or_qfi_ul; TODO: add this field when it works
// u16 src_port;
// u16 dest_port;
// Add other relevant parameters as needed
struct s_traffic {
u32 src_ip;
u8 protocol;
u32 dest_ip;
};
#endif // __TRAFFIC_H__
\ No newline at end of file
#ifndef __UE_TEID_QFI_MATCHING_H__
#define __UE_TEID_QFI_MATCHING_H__
#include <types.h>
#include <stdint.h>
struct s_ue_qfi {
u32 src_ip;
u8 qfi;
};
#endif // __UE_TEID_QFI_MATCHING_H__
\ No newline at end of file
......@@ -9,7 +9,7 @@
#include <signal.h> // signals
#include <pfcp_session_lookup_ebpf_xdp_prgrm_kernel_skel.h>
#include <wrappers/BPFMap.hpp>
#include "qfi_flow_mapping_table.h"
// #include "qfi_flow_mapping_table.h"
class BPFMaps;
class BPFMap;
......@@ -148,8 +148,8 @@ class PFCP_Session_LookupProgram {
*/
void initializeMaps();
void instrementQfiFlowMappingTable(
e_resource_type type, uint32_t qos, uint8_t qfi, uint8_t dscp);
// void instrementQfiFlowMappingTable(
// e_resource_type type, uint32_t qos, uint8_t qfi, uint8_t dscp);
/*****************************************************************************************************************/
// The reference of the bpf maps.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment