Skip to content

Commit

Permalink
fragmentation-reassembly (WIP)
Browse files Browse the repository at this point in the history
  • Loading branch information
GIC-de committed Oct 9, 2024
1 parent 1e24846 commit f85097d
Show file tree
Hide file tree
Showing 6 changed files with 138 additions and 0 deletions.
4 changes: 4 additions & 0 deletions code/bngblaster/src/bbl.c
Original file line number Diff line number Diff line change
Expand Up @@ -527,6 +527,10 @@ main(int argc, char *argv[])
if(igmp_group_count) g_ctx->config.igmp_group_count = atoi(igmp_group_count);
if(igmp_zap_interval) g_ctx->config.igmp_zap_interval = atoi(igmp_zap_interval);

if(g_ctx->config.stream_fragmentation_buffers) {
g_ctx->ipv4_fragments = calloc(g_ctx->config.stream_fragmentation_buffers, sizeof(bbl_ipv4_fragment_s));
}

#ifdef BNGBLASTER_DPDK
/* Init DPDK. */
if(!io_dpdk_init()) {
Expand Down
114 changes: 114 additions & 0 deletions code/bngblaster/src/bbl_access.c
Original file line number Diff line number Diff line change
Expand Up @@ -623,6 +623,119 @@ bbl_access_rx_ipv4_mc(bbl_access_interface_s *interface,
}
}

static void
ipv4_fragment_free(bbl_ipv4_fragment_s *fragment)
{
memset(fragment, 0x0, sizeof(bbl_ipv4_fragment_s)-sizeof(fragment->buf));
}

static void
bbl_access_rx_ipv4_fragments(bbl_access_interface_s *interface,
bbl_ethernet_header_s *eth, bbl_ipv4_s *ipv4)
{
if(!g_ctx->config.stream_fragmentation_buffers) return;

bbl_ipv4_fragment_s *fragment;
bbl_ipv4_fragment_s *free = NULL;
bbl_ipv4_fragment_s *oldest = &g_ctx->ipv4_fragments[0];

bbl_stream_s *stream;

uint8_t *bbl_start;
bbl_bbl_s bbl;

uint16_t offset;

int i; bool found = false;
for(i = 0; i < g_ctx->config.stream_fragmentation_buffers; i++) {
fragment = &g_ctx->ipv4_fragments[i];
if(fragment->id == ipv4->id &&
fragment->src == ipv4->src &&
fragment->dst == ipv4->dst) {
found = true;
break;
}
if(!free) {
if(!(fragment->src || fragment->dst)) {
free = fragment;
} else if(fragment->timestamp < oldest->timestamp) {
oldest = fragment;
}
}
}
if(!found) {
if(free) {
fragment = free;
} else {
fragment = oldest;
}
ipv4_fragment_free(fragment);
fragment->id = ipv4->id;
fragment->src = ipv4->src;
fragment->dst = ipv4->dst;
}
fragment->fragments++;
fragment->timestamp = eth->timestamp.tv_sec;

offset = ipv4->offset & 0x1FFF;
if(offset+ipv4->payload_len > sizeof(fragment->buf)) {
ipv4_fragment_free(fragment);
return;
}

memcpy(fragment->buf+offset, ipv4->payload, ipv4->payload_len);
fragment->recived += ipv4->payload_len;

if(!(ipv4->offset & IPV4_MF)) {
/* Last fragment recieved. */
fragment->expected = ipv4->offset + ipv4->payload_len;
}

if(fragment->recived == fragment->expected) {
/* All fragments received. */
if(packet_is_bbl(fragment->buf, fragment->recived)) {
/* Currently, we support only the reassembly of BBL stream packets. */
bbl_start = fragment->buf + (fragment->recived-BBL_HEADER_LEN);
bbl.type = *(bbl_start+8);
bbl.sub_type = *(bbl_start+9);
bbl.direction = *(bbl_start+10);
bbl.tos = *(bbl_start+11);
bbl.session_id = *(uint32_t*)(bbl_start+12);
if(bbl.type == BBL_TYPE_UNICAST) {
bbl.ifindex = *(uint32_t*)(bbl_start+16);
bbl.outer_vlan_id = *(uint16_t*)(bbl_start+20);
bbl.inner_vlan_id = *(uint16_t*)(bbl_start+22);
bbl.mc_source = 0;
bbl.mc_source = 0;
} else {
bbl.mc_source = *(uint32_t*)(bbl_start+16);
bbl.mc_source = *(uint32_t*)(bbl_start+20);
bbl.ifindex = 0;
bbl.outer_vlan_id = 0;
bbl.inner_vlan_id = 0;
}
bbl.flow_id = *(uint64_t*)(bbl_start+24);
bbl.flow_seq = *(uint64_t*)(bbl_start+32);
bbl.timestamp.tv_sec = *(uint32_t*)(bbl_start+40);
bbl.timestamp.tv_nsec = *(uint32_t*)(bbl_start+44);

eth->bbl = &bbl;
eth->length = (eth->length - ipv4->payload_len) + fragment->recived;

stream = bbl_stream_rx(eth, NULL);
if(stream) {
if(stream->rx_access_interface == NULL) {
stream->rx_access_interface = interface;
}
if(fragment->fragments > stream->rx_fragments) {
stream->rx_fragments = fragment->fragments;
}
}
}
ipv4_fragment_free(fragment);
}
}

static void
bbl_access_rx_ipv4(bbl_access_interface_s *interface,
bbl_session_s *session,
Expand All @@ -636,6 +749,7 @@ bbl_access_rx_ipv4(bbl_access_interface_s *interface,
session->stats.accounting_bytes_rx += eth->length;
session->stats.ipv4_fragmented_rx++;
interface->stats.ipv4_fragmented_rx++;
bbl_access_rx_ipv4_fragments(interface, eth, ipv4);
return;
}

Expand Down
5 changes: 5 additions & 0 deletions code/bngblaster/src/bbl_config.c
Original file line number Diff line number Diff line change
Expand Up @@ -3499,6 +3499,7 @@ json_parse_config(json_t *root)
"stream-rate-calculation",
"stream-delay-calculation",
"stream-burst-ms",
"stream-fragmentation-buffers",
"multicast-autostart",
"udp-checksum"
};
Expand Down Expand Up @@ -3531,6 +3532,10 @@ json_parse_config(json_t *root)
if(value) {
g_ctx->config.stream_burst_ms = json_number_value(value) * MSEC;
}
JSON_OBJ_GET_NUMBER(section, value, "traffic", "stream-fragmentation-buffers", 0, UINT16_MAX);
if(value) {
g_ctx->config.stream_fragmentation_buffers = json_number_value(value);
}
JSON_OBJ_GET_BOOL(section, value, "traffic", "multicast-autostart");
if(value) {
g_ctx->config.multicast_traffic_autostart = json_boolean_value(value);
Expand Down
3 changes: 3 additions & 0 deletions code/bngblaster/src/bbl_ctx.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ typedef struct bbl_ctx_
ldp_instance_s *ldp_instances;
ldp_raw_update_s *ldp_raw_updates;

bbl_ipv4_fragment_s *ipv4_fragments;

/* Scratchpad memory */
uint8_t *sp;

Expand Down Expand Up @@ -335,6 +337,7 @@ typedef struct bbl_ctx_
bool stream_delay_calc; /* Enable/disable stream delay calculation */
bool stream_udp_checksum; /* Enable/disable stream UDP checksum calculation */
uint64_t stream_burst_ms; /* Max bust size per stream in milliseconds */
uint16_t stream_fragmentation_buffers;

/* Session Traffic */
bool session_traffic_autostart;
Expand Down
11 changes: 11 additions & 0 deletions code/bngblaster/src/bbl_protocols.h
Original file line number Diff line number Diff line change
Expand Up @@ -784,6 +784,17 @@ typedef struct bbl_ipv4_ {
uint16_t payload_len; /* IPv4 payload length */
} bbl_ipv4_s;

typedef struct bbl_ipv4_fragment_ {
uint32_t timestamp;
uint32_t src;
uint32_t dst;
uint16_t id;
uint16_t fragments;
uint16_t recived;
uint16_t expected;
uint8_t buf[4076];
} bbl_ipv4_fragment_s;

/*
* IPv6 Structure
*/
Expand Down
1 change: 1 addition & 0 deletions code/bngblaster/src/bbl_stream.h
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,7 @@ typedef struct bbl_stream_
__time_t rx_interface_changed_epoch;
uint8_t rx_interface_changes;

uint8_t rx_fragments;
uint8_t rx_ttl; /* IPv4 or IPv6 TTL */
uint8_t rx_priority; /* IPv4 TOS or IPv6 TC */
uint8_t rx_outer_vlan_pbit;
Expand Down

0 comments on commit f85097d

Please sign in to comment.