@@ -63,6 +63,12 @@ __thread unsigned int per_lcore__lcore_id = 0;
6363/* nb_dev_ports defined in ff_dpdk_if.c (which we don't link here) */
6464int nb_dev_ports = 0 ;
6565
66+ /* FU-S7-KNI-ENABLE: with -DFF_KNI compiled into ff_dpdk_kni.o, the lib
67+ * references `extern int enable_kni;` (defined in ff_dpdk_if.c which we
68+ * do NOT link). Provide the stub here; tests that need the
69+ * (!enable_kni) false-leg flip it to 1 around the call. */
70+ int enable_kni = 0 ;
71+
6672/* ------------------------------------------------------------------------ */
6773/* Module-level EAL/mempool/ring (one-time init via rte_eal_init) */
6874/* ------------------------------------------------------------------------ */
@@ -399,6 +405,186 @@ test_ff_kni_init_tcp_udp_port_bitmaps(void **state)
399405 kni_stat = saved_kni_stat ;
400406}
401407
408+ /* ======================================================================== */
409+ /* Stage-7 follow-up FU-S7-KNI-ENABLE: branches gated by -DFF_KNI */
410+ /* ======================================================================== */
411+
412+ #ifndef IPPROTO_OSPFIGP
413+ #define IPPROTO_OSPFIGP 89
414+ #endif
415+
416+ /* Helper: build a minimal IPv4 packet starting with version+IHL byte; the
417+ * caller patches proto and (optionally) appends an L4 header. The
418+ * packet's IPv4 header length is exactly 20 bytes (IHL=5). */
419+ static void
420+ ff_test_build_ipv4 (uint8_t * buf , size_t buf_len , uint8_t proto )
421+ {
422+ memset (buf , 0 , buf_len );
423+ buf [0 ] = 0x45 ; /* version=4 IHL=5 */
424+ buf [9 ] = proto ; /* next-proto */
425+ }
426+
427+ /* TC-S7-KNI-12: IPv4+OSPF (proto=89) -> FILTER_OSPF. Covers the FF_KNI-
428+ * gated `case IPPROTO_OSPFIGP: return FILTER_OSPF;` branch (L335-338). */
429+ static void
430+ test_ff_kni_proto_filter_ipv4_ospf_returns_ospf (void * * state )
431+ {
432+ (void )state ;
433+ uint8_t pkt [64 ];
434+ ff_test_build_ipv4 (pkt , sizeof (pkt ), IPPROTO_OSPFIGP );
435+ enum FilterReturn rv = ff_kni_proto_filter (pkt , sizeof (pkt ),
436+ RTE_ETHER_TYPE_IPV4 );
437+ assert_int_equal (rv , FILTER_OSPF );
438+ }
439+
440+ /* TC-S7-KNI-13: IPv4+TCP with enable_kni=1 and a too-short L4 fragment
441+ * after the IP header -> FILTER_UNKNOWN via protocol_filter_tcp's
442+ * `len < sizeof(rte_tcp_hdr)` true leg (L209 br=0). */
443+ static void
444+ test_ff_kni_proto_filter_ipv4_tcp_kni_enabled_short (void * * state )
445+ {
446+ (void )state ;
447+ /* IP hdr 20 + 5 bytes TCP fragment (< sizeof(rte_tcp_hdr)=20). */
448+ uint8_t pkt [25 ];
449+ ff_test_build_ipv4 (pkt , sizeof (pkt ), IPPROTO_TCP );
450+
451+ int saved = enable_kni ; enable_kni = 1 ;
452+ enum FilterReturn rv = ff_kni_proto_filter (pkt , sizeof (pkt ),
453+ RTE_ETHER_TYPE_IPV4 );
454+ enable_kni = saved ;
455+ assert_int_equal (rv , FILTER_UNKNOWN );
456+ }
457+
458+ /* TC-S7-KNI-14: IPv4+UDP with enable_kni=1 and a too-short L4 fragment
459+ * -> FILTER_UNKNOWN via protocol_filter_udp's len<hdr true leg (L221). */
460+ static void
461+ test_ff_kni_proto_filter_ipv4_udp_kni_enabled_short (void * * state )
462+ {
463+ (void )state ;
464+ /* IP hdr 20 + 5 bytes UDP fragment (< sizeof(rte_udp_hdr)=8). */
465+ uint8_t pkt [25 ];
466+ ff_test_build_ipv4 (pkt , sizeof (pkt ), IPPROTO_UDP );
467+
468+ int saved = enable_kni ; enable_kni = 1 ;
469+ enum FilterReturn rv = ff_kni_proto_filter (pkt , sizeof (pkt ),
470+ RTE_ETHER_TYPE_IPV4 );
471+ enable_kni = saved ;
472+ assert_int_equal (rv , FILTER_UNKNOWN );
473+ }
474+
475+ /* TC-S7-KNI-15: enable_kni=1, ff_kni_init had registered TCP port 80 in
476+ * the bitmap, packet has dst_port=80 (network order) -> FILTER_KNI.
477+ * Covers protocol_filter_l4's true leg (L199) AND the `if (!enable_kni)`
478+ * false leg in the IPPROTO_TCP case (L342). */
479+ static void
480+ test_ff_kni_proto_filter_ipv4_tcp_kni_enabled_match_returns_kni (void * * state )
481+ {
482+ (void )state ;
483+ SKIP_IF_NO_EAL ();
484+
485+ /* (Re)build the port bitmaps under our control. Save+restore the
486+ * caller-managed kni_rp/kni_stat as the existing TC-U-P3-KNI-11 does. */
487+ struct rte_ring * * saved_kni_rp = kni_rp ;
488+ struct kni_interface_stats * * saved_kni_stat = kni_stat ;
489+ ff_kni_init (/*nb_ports*/ 1 , /*tcp*/ "80" , /*udp*/ "53" );
490+ rte_free (kni_rp );
491+ rte_free (kni_stat );
492+ kni_rp = saved_kni_rp ;
493+ kni_stat = saved_kni_stat ;
494+
495+ /* IPv4(20) + TCP(20). dst_port lives at IP hdr offset 20 + TCP byte 2..3. */
496+ uint8_t pkt [40 ];
497+ ff_test_build_ipv4 (pkt , sizeof (pkt ), IPPROTO_TCP );
498+ /* dst_port=80 in network byte order. set_bitmap stores the htons-ed
499+ * port; get_bitmap is called with hdr->dst_port (already big-endian),
500+ * so writing 0x00,0x50 directly produces the same bit index. */
501+ pkt [20 + 2 ] = 0x00 ;
502+ pkt [20 + 3 ] = 0x50 ;
503+
504+ int saved = enable_kni ; enable_kni = 1 ;
505+ enum FilterReturn rv = ff_kni_proto_filter (pkt , sizeof (pkt ),
506+ RTE_ETHER_TYPE_IPV4 );
507+ enable_kni = saved ;
508+ assert_int_equal (rv , FILTER_KNI );
509+ }
510+
511+ /* TC-S7-KNI-16: enable_kni=1, packet has dst_port=8080 NOT in the bitmap
512+ * -> FILTER_UNKNOWN (protocol_filter_l4 false leg, L199 br=0). */
513+ static void
514+ test_ff_kni_proto_filter_ipv4_tcp_kni_enabled_miss_returns_unknown (void * * state )
515+ {
516+ (void )state ;
517+ SKIP_IF_NO_EAL ();
518+
519+ struct rte_ring * * saved_kni_rp = kni_rp ;
520+ struct kni_interface_stats * * saved_kni_stat = kni_stat ;
521+ ff_kni_init (1 , "80" , "53" );
522+ rte_free (kni_rp );
523+ rte_free (kni_stat );
524+ kni_rp = saved_kni_rp ;
525+ kni_stat = saved_kni_stat ;
526+
527+ uint8_t pkt [40 ];
528+ ff_test_build_ipv4 (pkt , sizeof (pkt ), IPPROTO_TCP );
529+ /* dst_port=8080=0x1F90 in network order. */
530+ pkt [20 + 2 ] = 0x1F ;
531+ pkt [20 + 3 ] = 0x90 ;
532+
533+ int saved = enable_kni ; enable_kni = 1 ;
534+ enum FilterReturn rv = ff_kni_proto_filter (pkt , sizeof (pkt ),
535+ RTE_ETHER_TYPE_IPV4 );
536+ enable_kni = saved ;
537+ assert_int_equal (rv , FILTER_UNKNOWN );
538+ }
539+
540+ /* TC-S7-KNI-17: enable_kni=1 + UDP dst_port=53 matches bitmap -> FILTER_KNI.
541+ * Covers `if (!enable_kni)` false leg in IPPROTO_UDP case (L350). */
542+ static void
543+ test_ff_kni_proto_filter_ipv4_udp_kni_enabled_match_returns_kni (void * * state )
544+ {
545+ (void )state ;
546+ SKIP_IF_NO_EAL ();
547+
548+ struct rte_ring * * saved_kni_rp = kni_rp ;
549+ struct kni_interface_stats * * saved_kni_stat = kni_stat ;
550+ ff_kni_init (1 , "80" , "53" );
551+ rte_free (kni_rp );
552+ rte_free (kni_stat );
553+ kni_rp = saved_kni_rp ;
554+ kni_stat = saved_kni_stat ;
555+
556+ /* IPv4(20) + UDP(8). dst_port=53 (0x0035) at IP+2..3. */
557+ uint8_t pkt [28 ];
558+ ff_test_build_ipv4 (pkt , sizeof (pkt ), IPPROTO_UDP );
559+ pkt [20 + 2 ] = 0x00 ;
560+ pkt [20 + 3 ] = 0x35 ;
561+
562+ int saved = enable_kni ; enable_kni = 1 ;
563+ enum FilterReturn rv = ff_kni_proto_filter (pkt , sizeof (pkt ),
564+ RTE_ETHER_TYPE_IPV4 );
565+ enable_kni = saved ;
566+ assert_int_equal (rv , FILTER_KNI );
567+ }
568+
569+ /* TC-S7-KNI-18: ff_kni_init with NULL tcp_ports / udp_ports exercises
570+ * kni_set_bitmap's L114 `if(!p) return;` early-return branch. */
571+ static void
572+ test_ff_kni_init_null_port_lists (void * * state )
573+ {
574+ (void )state ;
575+ SKIP_IF_NO_EAL ();
576+
577+ struct rte_ring * * saved_kni_rp = kni_rp ;
578+ struct kni_interface_stats * * saved_kni_stat = kni_stat ;
579+ /* Both args NULL — kni_set_bitmap is invoked twice and returns
580+ * immediately on the !p check. Init must still succeed. */
581+ ff_kni_init (/*nb_ports*/ 1 , /*tcp*/ NULL , /*udp*/ NULL );
582+ rte_free (kni_rp );
583+ rte_free (kni_stat );
584+ kni_rp = saved_kni_rp ;
585+ kni_stat = saved_kni_stat ;
586+ }
587+
402588/* ------------------------------------------------------------------------ */
403589/* Main runner */
404590/* ------------------------------------------------------------------------ */
@@ -418,6 +604,14 @@ main(void)
418604 cmocka_unit_test_setup_teardown (test_ff_kni_proto_filter_ipv4_oversized_ihl , test_setup , NULL ),
419605 cmocka_unit_test_setup_teardown (test_ff_kni_proto_filter_ipv4_ipip_recurse , test_setup , NULL ),
420606 cmocka_unit_test_setup_teardown (test_ff_kni_init_tcp_udp_port_bitmaps , test_setup , NULL ),
607+ /* Stage-7 follow-up FU-S7-KNI-ENABLE: branches gated by -DFF_KNI */
608+ cmocka_unit_test_setup_teardown (test_ff_kni_proto_filter_ipv4_ospf_returns_ospf , test_setup , NULL ),
609+ cmocka_unit_test_setup_teardown (test_ff_kni_proto_filter_ipv4_tcp_kni_enabled_short , test_setup , NULL ),
610+ cmocka_unit_test_setup_teardown (test_ff_kni_proto_filter_ipv4_udp_kni_enabled_short , test_setup , NULL ),
611+ cmocka_unit_test_setup_teardown (test_ff_kni_proto_filter_ipv4_tcp_kni_enabled_match_returns_kni , test_setup , NULL ),
612+ cmocka_unit_test_setup_teardown (test_ff_kni_proto_filter_ipv4_tcp_kni_enabled_miss_returns_unknown , test_setup , NULL ),
613+ cmocka_unit_test_setup_teardown (test_ff_kni_proto_filter_ipv4_udp_kni_enabled_match_returns_kni , test_setup , NULL ),
614+ cmocka_unit_test_setup_teardown (test_ff_kni_init_null_port_lists , test_setup , NULL ),
421615 };
422616 return cmocka_run_group_tests (tests , group_setup , group_teardown );
423617}
0 commit comments