Skip to content

Commit

Permalink
Merge pull request #622 from AltraMayor/long-rss
Browse files Browse the repository at this point in the history
gatekeeper: support variable sizes of RSS hash keys
  • Loading branch information
AltraMayor authored Oct 31, 2022
2 parents 3c29696 + 6f009ac commit 99b31a8
Show file tree
Hide file tree
Showing 8 changed files with 339 additions and 261 deletions.
3 changes: 2 additions & 1 deletion ggu/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,9 @@ static struct ggu_config *ggu_conf;
static void
process_single_policy(struct ggu_policy *policy, void *arg)
{
uint32_t flow_hash_val = rss_ip_flow_hf(&policy->flow, 0, 0);
const struct ggu_config *ggu_conf = arg;
uint32_t flow_hash_val = rss_flow_hash(&ggu_conf->net->front,
&policy->flow);
struct gk_cmd_entry *entry;
/*
* Obtain mailbox of that GK block,
Expand Down
28 changes: 24 additions & 4 deletions gk/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -846,7 +846,7 @@ gk_del_flow_entry_with_key(struct gk_instance *instance,
return gk_del_flow_entry_at_pos(instance, entry_idx);
}

if (likely(flow_key_eq(flow_key, &fe->flow)))
if (likely(flow_equal(flow_key, &fe->flow)))
return gk_del_flow_entry_at_pos(instance, entry_idx);

found_corruption_in_flow_table(instance);
Expand All @@ -873,6 +873,26 @@ gk_del_flow_entry_with_key(struct gk_instance *instance,
gk_del_flow_entry_at_pos(instance, entry_idx);
}

static uint32_t
rss_ip_flow_hf(const void *data,
__attribute__((unused)) uint32_t data_len,
__attribute__((unused)) uint32_t init_val)
{
/*
* XXX #375 Ideally, @init_val would be of the type (void *),
* so one would not need to rely on calling get_net_conf() to
* get @front.
*/
return rss_flow_hash(&get_net_conf()->front, data);
}

static int
ip_flow_cmp_eq(const void *key1, const void *key2,
__attribute__((unused)) size_t key_len)
{
return flow_cmp(key1, key2);
}

static int
setup_gk_instance(unsigned int lcore_id, struct gk_config *gk_conf)
{
Expand Down Expand Up @@ -1848,7 +1868,7 @@ parse_packet(struct ipacket *packet, struct rte_mbuf *pkt,

flow_arr[*num_ip_flows] = &packet->flow;
flow_hash_val_arr[*num_ip_flows] = likely(front->rss) ?
pkt->hash.rss : rss_ip_flow_hf(&packet->flow, 0, 0);
pkt->hash.rss : rss_flow_hash(front, &packet->flow);
(*num_ip_flows)++;
}

Expand Down Expand Up @@ -2494,7 +2514,7 @@ test_invalid_flow(__attribute__((unused)) void *arg,
const struct ip_flow *flow, struct flow_entry *fe)
{
if (unlikely(!is_flow_valid(flow) || !is_flow_valid(&fe->flow) ||
!flow_key_eq(flow, &fe->flow) ||
!flow_equal(flow, &fe->flow) ||
!fe->in_use || fe->grantor_fib == NULL ||
fe->grantor_fib->action != GK_FWD_GRANTOR
))
Expand Down Expand Up @@ -3146,7 +3166,7 @@ gk_log_flow_state(const char *src_addr,
flow.f.v6.dst = dst.ip.v6;
}

flow_hash_val = rss_ip_flow_hf(&flow, 0, 0);
flow_hash_val = rss_flow_hash(&gk_conf->net->front, &flow);

mb = get_responsible_gk_mailbox(flow_hash_val, gk_conf);
if (mb == NULL) {
Expand Down
9 changes: 3 additions & 6 deletions include/gatekeeper_flow.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,12 @@ struct ip_flow {
} f;
};

uint32_t rss_ip_flow_hf(const void *data,
uint32_t data_len, uint32_t init_val);

int ip_flow_cmp_eq(const void *key1, const void *key2, size_t key_len);
int flow_cmp(const struct ip_flow *flow1, const struct ip_flow *flow2);

static inline bool
flow_key_eq(const struct ip_flow *f1, const struct ip_flow *f2)
flow_equal(const struct ip_flow *flow1, const struct ip_flow *flow2)
{
return ip_flow_cmp_eq(f1, f2, sizeof(*f1)) == 0;
return flow_cmp(flow1, flow2) == 0;
}

void print_flow_err_msg(const struct ip_flow *flow, int32_t index,
Expand Down
41 changes: 30 additions & 11 deletions include/gatekeeper_net.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,14 @@ struct ipaddr {
} ip;
};

/* Size of the secret key of the RSS hash. */
#define GATEKEEPER_RSS_KEY_LEN (40)
/*
* The minimum and maximum sizes of the (secret) RSS hash key.
*
* These constants MUST be multiples of 4 since functions such
* rte_convert_rss_key() expects so.
*/
#define GATEKEEPER_RSS_MIN_KEY_LEN (40)
#define GATEKEEPER_RSS_MAX_KEY_LEN (128)

/*
* The maximum number of "rte_eth_rss_reta_entry64" structures can be used to
Expand Down Expand Up @@ -234,6 +240,12 @@ struct gatekeeper_if {
/* Whether IPv4 (L3) checksums should be enabled in hardware. */
bool ipv4_hw_cksum;

/*
* This field decides if the flag GRND_RANDOM is passed to getradom(2)
* while initializing field @rss_key.
*/
bool guarantee_random_entropy;

/*
* The fields below are for internal use.
* Configuration files should not refer to them.
Expand Down Expand Up @@ -350,8 +362,24 @@ struct gatekeeper_if {

/* Whether the interface has been initialized. */
bool alive;

/* Length of the RSS key in bytes. */
uint8_t rss_key_len;

/*
* RSS hash key.
*
* The secret key of the RSS hash (RSK) must be random in order
* to prevent hackers from knowing it.
*/
uint8_t rss_key[GATEKEEPER_RSS_MAX_KEY_LEN];
/* @rss_key ready for use with rte_softrss_be(). */
uint8_t rss_key_be[GATEKEEPER_RSS_MAX_KEY_LEN];
};

uint32_t rss_flow_hash(const struct gatekeeper_if *iface,
const struct ip_flow *flow);

/*
* The atomic counters for @rx_queue_id and @tx_queue_id are
* signed, so we get about 2^15 possible queues available for use,
Expand Down Expand Up @@ -382,12 +410,6 @@ struct net_config {
*/
int back_iface_enabled;

/*
* This parameter is used to decide if flag GRND_RANDOM
* should be passed to any call of getradom(2).
*/
int guarantee_random_entropy;

/*
* Number of attempts to wait for Gatekeeper links to
* come up during initialization.
Expand Down Expand Up @@ -424,9 +446,6 @@ struct net_config {
gid_t pw_gid;
};

extern uint8_t default_rss_key[GATEKEEPER_RSS_KEY_LEN];
extern uint8_t rss_key_be[RTE_DIM(default_rss_key)];

/*
* Initializes an array of 16 bytes that represents the IPv6 solicited
* node multicast address. Users of this macro need to pass the IPv6
Expand Down
89 changes: 7 additions & 82 deletions lib/flow.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,94 +23,19 @@
#include <rte_ether.h>

#include "gatekeeper_net.h"
#include "gatekeeper_flow.h"
#include "gatekeeper_main.h"
#include "gatekeeper_flow.h"

/*
* Optimized generic implementation of RSS hash function.
* If you want the calculated hash value matches NIC RSS value,
* you have to use special converted key with rte_convert_rss_key() fn.
* @param input_tuple
* Pointer to input tuple with network order.
* @param input_len
* Length of input_tuple in 4-bytes chunks.
* @param *rss_key
* Pointer to RSS hash key.
* @return
* Calculated hash value.
*/
static inline uint32_t
gk_softrss_be(const uint32_t *input_tuple, uint32_t input_len,
const uint8_t *rss_key)
{
uint32_t i;
uint32_t j;
uint32_t ret = 0;

for (j = 0; j < input_len; j++) {
/*
* Need to use little endian,
* since it takes ordering as little endian in both bytes and bits.
*/
uint32_t val = rte_be_to_cpu_32(input_tuple[j]);
for (i = 0; i < 32; i++)
if (val & (1 << (31 - i))) {
/*
* The cast (uint64_t) is needed because when
* @i == 0, the expression requires a 32-bit
* shift of a 32-bit unsigned integer,
* what is undefined.
* The C standard only defines bit shifting
* up to the bit-size of the integer minus one.
* Finally, the cast (uint32_t) avoid promoting
* the expression before the bit-or (i.e. `|`)
* to uint64_t.
*/
ret ^= ((const uint32_t *)rss_key)[j] << i |
(uint32_t)((uint64_t)
(((const uint32_t *)rss_key)
[j + 1])
>> (32 - i));
}
}

return ret;
}

uint32_t
rss_ip_flow_hf(const void *data,
__attribute__((unused)) uint32_t data_len,
__attribute__((unused)) uint32_t init_val)
{
const struct ip_flow *flow = (const struct ip_flow *)data;

if (flow->proto == RTE_ETHER_TYPE_IPV4)
return gk_softrss_be((const uint32_t *)&flow->f,
(sizeof(flow->f.v4)/sizeof(uint32_t)), rss_key_be);
else if (flow->proto == RTE_ETHER_TYPE_IPV6)
return gk_softrss_be((const uint32_t *)&flow->f,
(sizeof(flow->f.v6)/sizeof(uint32_t)), rss_key_be);
else
rte_panic("Unexpected protocol: %i\n", flow->proto);

return 0;
}

/* Type of function used to compare the hash key. */
int
ip_flow_cmp_eq(const void *key1, const void *key2,
__attribute__((unused)) size_t key_len)
flow_cmp(const struct ip_flow *flow1, const struct ip_flow *flow2)
{
const struct ip_flow *f1 = (const struct ip_flow *)key1;
const struct ip_flow *f2 = (const struct ip_flow *)key2;
if (flow1->proto != flow2->proto)
return flow1->proto == RTE_ETHER_TYPE_IPV4 ? -1 : 1;

if (f1->proto != f2->proto)
return f1->proto == RTE_ETHER_TYPE_IPV4 ? -1 : 1;
if (flow1->proto == RTE_ETHER_TYPE_IPV4)
return memcmp(&flow1->f.v4, &flow2->f.v4, sizeof(flow1->f.v4));

if (f1->proto == RTE_ETHER_TYPE_IPV4)
return memcmp(&f1->f.v4, &f2->f.v4, sizeof(f1->f.v4));
else
return memcmp(&f1->f.v6, &f2->f.v6, sizeof(f1->f.v6));
return memcmp(&flow1->f.v6, &flow2->f.v6, sizeof(flow1->f.v6));
}

static void
Expand Down
Loading

0 comments on commit 99b31a8

Please sign in to comment.