@@ -390,6 +390,28 @@ static bool is_rate_limited(__u64 now, __u64 last_ts, __u64 rtt)
390390 return now - last_ts < config .rate_limit ;
391391}
392392
393+ /*
394+ * Send a flow opening event through the perf-buffer.
395+ * As these events are only sent upon receiving a reply, need to access state
396+ * of the reverse flow to get reason flow was opened and when the original
397+ * packet opening the flow was sent.
398+ */
399+ static void send_flow_open_event (void * ctx , struct packet_info * p_info ,
400+ struct flow_state * rev_flow )
401+ {
402+ struct flow_event fe = {
403+ .event_type = EVENT_TYPE_FLOW ,
404+ .flow_event_type = FLOW_EVENT_OPENING ,
405+ .source = EVENT_SOURCE_PKT_DEST ,
406+ .flow = p_info -> pid .flow ,
407+ .reason = rev_flow -> opening_reason ,
408+ .timestamp = rev_flow -> last_timestamp ,
409+ .reserved = 0 ,
410+ };
411+
412+ bpf_perf_event_output (ctx , & events , BPF_F_CURRENT_CPU , & fe , sizeof (fe ));
413+ }
414+
393415/*
394416 * Sends a flow-event message based on p_info.
395417 *
@@ -420,24 +442,22 @@ static void send_flow_event(void *ctx, struct packet_info *p_info,
420442}
421443
422444/*
423- * Attempt to create a new flow-state and push flow-opening message
445+ * Attempt to create a new flow-state.
424446 * Returns a pointer to the flow_state if successful, NULL otherwise
425447 */
426- static struct flow_state * create_flow (void * ctx , struct packet_info * p_info )
448+ static struct flow_state * create_flow (struct packet_info * p_info )
427449{
428450 struct flow_state new_state = { 0 };
429451
430452 new_state .last_timestamp = p_info -> time ;
453+ new_state .opening_reason = p_info -> event_type == FLOW_EVENT_OPENING ?
454+ p_info -> event_reason :
455+ EVENT_REASON_FIRST_OBS_PCKT ;
456+
431457 if (bpf_map_update_elem (& flow_state , & p_info -> pid .flow , & new_state ,
432458 BPF_NOEXIST ) != 0 )
433459 return NULL ;
434460
435- if (p_info -> event_type != FLOW_EVENT_OPENING ) {
436- p_info -> event_type = FLOW_EVENT_OPENING ;
437- p_info -> event_reason = EVENT_REASON_FIRST_OBS_PCKT ;
438- }
439- send_flow_event (ctx , p_info , false);
440-
441461 return bpf_map_lookup_elem (& flow_state , & p_info -> pid .flow );
442462}
443463
@@ -448,46 +468,68 @@ static struct flow_state *update_flow(void *ctx, struct packet_info *p_info,
448468 * new_flow = false;
449469
450470 f_state = bpf_map_lookup_elem (& flow_state , & p_info -> pid .flow );
451- if (!f_state && p_info -> pid_valid ) {
471+
472+ // Attempt to create flow if it does not exist
473+ if (!f_state && p_info -> pid_valid &&
474+ !(p_info -> event_type == FLOW_EVENT_CLOSING ||
475+ p_info -> event_type == FLOW_EVENT_CLOSING_BOTH )) {
452476 * new_flow = true;
453- f_state = create_flow (ctx , p_info );
477+ f_state = create_flow (p_info );
454478 }
455479
456480 if (!f_state )
457481 return NULL ;
458482
483+ // Update flow state
459484 f_state -> sent_pkts ++ ;
460485 f_state -> sent_bytes += p_info -> payload ;
461486
462487 return f_state ;
463488}
464489
465- static struct flow_state * update_rev_flow (struct packet_info * p_info )
490+ static struct flow_state * update_rev_flow (void * ctx , struct packet_info * p_info )
466491{
467492 struct flow_state * f_state ;
468493
469494 f_state = bpf_map_lookup_elem (& flow_state , & p_info -> reply_pid .flow );
470495 if (!f_state )
471496 return NULL ;
472497
498+ // Is a new flow, push opening flow message
499+ if (!f_state -> has_opened &&
500+ p_info -> event_type != FLOW_EVENT_CLOSING_BOTH ) {
501+ f_state -> has_opened = true;
502+ send_flow_open_event (ctx , p_info , f_state );
503+ }
504+
505+ // Update flow state
473506 f_state -> rec_pkts ++ ;
474507 f_state -> rec_bytes += p_info -> payload ;
475508
476509 return f_state ;
477510}
478511
479- static void delete_closed_flows (void * ctx , struct packet_info * p_info )
512+ static void delete_closed_flows (void * ctx , struct packet_info * p_info ,
513+ struct flow_state * flow ,
514+ struct flow_state * rev_flow )
480515{
516+ bool has_opened ;
517+
481518 // Flow closing - try to delete flow state and push closing-event
482- if (p_info -> event_type == FLOW_EVENT_CLOSING ||
483- p_info -> event_type == FLOW_EVENT_CLOSING_BOTH ) {
484- if (!bpf_map_delete_elem (& flow_state , & p_info -> pid .flow ))
519+ if (flow && (p_info -> event_type == FLOW_EVENT_CLOSING ||
520+ p_info -> event_type == FLOW_EVENT_CLOSING_BOTH )) {
521+ has_opened = flow -> has_opened ;
522+ if (!bpf_map_delete_elem (& flow_state , & p_info -> pid .flow ) &&
523+ has_opened )
485524 send_flow_event (ctx , p_info , false);
486525 }
487526
488527 // Also close reverse flow
489- if (p_info -> event_type == FLOW_EVENT_CLOSING_BOTH ) {
490- if (!bpf_map_delete_elem (& flow_state , & p_info -> reply_pid .flow ))
528+ if (rev_flow && p_info -> event_type == FLOW_EVENT_CLOSING_BOTH ) {
529+ has_opened = rev_flow -> has_opened ;
530+ if (!bpf_map_delete_elem (& flow_state ,
531+ & p_info -> reply_pid .flow ) &&
532+ has_opened )
491533 send_flow_event (ctx , p_info , true);
492534 }
493535}
@@ -617,22 +659,20 @@ static void pping_match_packet(struct flow_state *f_state, void *ctx,
617659static void pping (void * ctx , struct parsing_context * pctx )
618660{
619661 struct packet_info p_info = { 0 };
620- struct flow_state * f_state ;
662+ struct flow_state * flow , * rev_flow ; ;
621663 bool new_flow ;
622664
623665 if (parse_packet_identifier (pctx , & p_info ) < 0 )
624666 return ;
625667
626- if ( p_info . event_type != FLOW_EVENT_CLOSING &&
627- p_info . event_type != FLOW_EVENT_CLOSING_BOTH ) {
628- f_state = update_flow ( ctx , & p_info , & new_flow );
629- pping_timestamp_packet ( f_state , ctx , pctx , & p_info , new_flow );
630- }
668+ flow = update_flow ( ctx , & p_info , & new_flow );
669+ pping_timestamp_packet ( flow , ctx , pctx , & p_info , new_flow );
670+
671+ rev_flow = update_rev_flow ( ctx , & p_info );
672+ pping_match_packet ( rev_flow , ctx , pctx , & p_info );
631673
632- f_state = update_rev_flow (& p_info );
633- pping_match_packet (f_state , ctx , pctx , & p_info );
674+ delete_closed_flows (ctx , & p_info , flow , rev_flow );
634675
635- delete_closed_flows (ctx , & p_info );
636676}
637677
638678// Programs
0 commit comments