CT: Perf optimization through prefetch and condition checks in CT 33/34433/3
authorAnand B Jyoti <anand.b.jyoti@intel.com>
Mon, 8 May 2017 05:34:07 +0000 (11:04 +0530)
committerDeepak S <deepak.s@linux.intel.com>
Thu, 1 Jun 2017 11:56:00 +0000 (11:56 +0000)
JIRA: SAMPLEVNF-10

LLC miss is possible when the connection data structure is accessed
after retrieved from hash table entries for TCP/UDP connection.
CPI for rte_ct_udp_packet() is not good due to if/else condition checks.
This patch provide a prefetch instructions to pre-fetch the cnxn data entry
structure to avoid the LLC miss and also optimize the if/else condition check
to improve the CPI for rte_ct_udp_packet() function.

Change-Id: Ieaf70815c919ddbe1ff34921222eac030fb41756
Signed-off-by: Anand B Jyoti <anand.b.jyoti@intel.com>
common/VIL/conntrack/rte_cnxn_tracking.c
common/VIL/conntrack/rte_ct_udp.c

index 461ed42..aa18058 100644 (file)
@@ -52,7 +52,6 @@
 
 #define IP_VERSION_4 4
 #define IP_VERSION_6 6
-
 static void
 rte_ct_cnxn_tracker_batch_lookup_basic_type(
        struct rte_ct_cnxn_tracker *ct,
@@ -1479,6 +1478,9 @@ rte_ct_cnxn_tracker_batch_lookup_basic_type(
        int32_t positions[RTE_HASH_LOOKUP_BULK_MAX];
        uint32_t i;
        struct rte_ct_cnxn_data new_cnxn_data;
+       struct rte_ct_cnxn_data *cnxn_data_entry[RTE_HASH_LOOKUP_BULK_MAX];
+
+       rte_prefetch0(ct->hash_table_entries);
 
        if (CNXN_TRX_DEBUG > 1) {
                printf("Enter cnxn tracker %p", ct);
@@ -1631,6 +1633,35 @@ rte_ct_cnxn_tracker_batch_lookup_basic_type(
                *pkts_mask = 0;
                return; /* unknown error, just discard all packets */
        }
+
+       /* Pre-fetch hash table entries and counters to avoid LLC miss */
+       rte_prefetch0(ct->counters);
+       for (i = 0; i < packets_for_lookup; i++) {
+               struct rte_ct_cnxn_data *entry = NULL;
+               int hash_table_entry = positions[i];
+
+               if (hash_table_entry >= 0) {
+                       /* Entry found for existing UDP/TCP connection */
+                       entry = &ct->hash_table_entries[hash_table_entry];
+                       rte_prefetch0(&entry->counters.packets_forwarded);
+                       rte_prefetch0(entry);
+                       rte_prefetch0(&entry->key_is_client_order);
+               }
+               else {
+                       uint8_t pkt_index = compacting_map[i];
+                       uint32_t *key = ct->hash_key_ptrs[pkt_index];
+                       uint8_t protocol = *(key + 9);
+                       if (protocol == UDP_PROTOCOL) {
+                               /* Search in new connections only for UDP */
+                               entry = rte_ct_search_new_connections(ct, key);
+                               rte_prefetch0(&entry->counters.packets_forwarded);
+                               rte_prefetch0(entry);
+                               rte_prefetch0(&entry->key_is_client_order);
+                       }
+               }
+               cnxn_data_entry[i] = entry;
+       }
+
        for (i = 0; i < packets_for_lookup; i++) {
                /* index into hash table entries */
                int hash_table_entry = positions[i];
@@ -1689,7 +1720,7 @@ rte_ct_cnxn_tracker_batch_lookup_basic_type(
                                 */
 
                                struct rte_ct_cnxn_data *entry =
-                               &ct->hash_table_entries[hash_table_entry];
+                                       cnxn_data_entry[i];
 
                                if (rte_ct_udp_packet
                                                (ct, entry, pkts[pkt_index],
@@ -1704,7 +1735,7 @@ rte_ct_cnxn_tracker_batch_lookup_basic_type(
                                 */
 
                                struct rte_ct_cnxn_data *recent_entry =
-                                       rte_ct_search_new_connections(ct, key);
+                                       cnxn_data_entry[i];
 
                                if (recent_entry != NULL) {
                                        if (rte_ct_udp_packet(ct, recent_entry,
index 88f3a9a..6caa788 100644 (file)
@@ -33,17 +33,17 @@ enum rte_ct_packet_action rte_ct_udp_packet(struct rte_ct_cnxn_tracker *ct,
                uint8_t  key_was_flipped)
 {
        enum rte_ct_pkt_direction dir;
-
+       enum rte_ct_udp_states ustate = RTE_CT_UDP_UNREPLIED;
        dir = (cd->key_is_client_order == !key_was_flipped);
        /* printf("packet received verify"); */
-       if (dir == RTE_CT_DIR_REPLY &&
-                       cd->connstatus == RTE_INIT_CONN) {
-               rte_ct_set_cnxn_timer_for_udp(ct, cd, RTE_CT_UDP_REPLIED);
+       if (dir == RTE_CT_DIR_REPLY && (
+                       (cd->connstatus == RTE_INIT_CONN) ||
+                       (cd->connstatus == RTE_ASSURED_CONN)))
+       {
+               ustate = RTE_CT_UDP_REPLIED;
                cd->connstatus = RTE_ASSURED_CONN;
-       } else if (dir == RTE_CT_DIR_REPLY &&
-                       cd->connstatus == RTE_ASSURED_CONN)
-               rte_ct_set_cnxn_timer_for_udp(ct, cd, RTE_CT_UDP_REPLIED);
-       else
-               rte_ct_set_cnxn_timer_for_udp(ct, cd, RTE_CT_UDP_UNREPLIED);
+       }
+       rte_ct_set_cnxn_timer_for_udp(ct, cd, ustate);
+
        return RTE_CT_FORWARD_PACKET;
 }