Skip to content

Commit

Permalink
Fix crash with more than 64 rss queues
Browse files Browse the repository at this point in the history
  • Loading branch information
cardigliano committed Jan 24, 2024
1 parent 2f57fb9 commit 2939557
Showing 1 changed file with 33 additions and 18 deletions.
51 changes: 33 additions & 18 deletions kernel/pf_ring.c
Original file line number Diff line number Diff line change
Expand Up @@ -502,6 +502,15 @@ void msleep(unsigned int msecs)

/* ************************************************** */

static inline u_int64_t get_channel_id_bit_mask(u_int32_t channel_id) {
if (channel_id >= MAX_NUM_RX_CHANNELS) /* safety check */
channel_id = MAX_NUM_RX_CHANNELS-1;

return ((u_int64_t) ((u_int64_t) 1) << channel_id);
}

/* ************************************************** */

static inline int32_t ifindex_to_pf_index(pf_ring_net *netns,
int32_t ifindex) {
ifindex_map_item *ifindex_map = netns->ifindex_map;
Expand Down Expand Up @@ -3129,14 +3138,13 @@ static inline int add_pkt_to_ring(struct sk_buff *skb,
int offset)
{
struct pf_ring_socket *pfr = (_pfr->master_ring != NULL) ? _pfr->master_ring : _pfr;
u_int64_t channel_id_bit = ((u_int64_t) ((u_int64_t) 1) << channel_id);

if((!pfr->ring_active) || (!skb))
return(0);

if((pfr->channel_id_mask != RING_ANY_CHANNEL)
&& (channel_id != -1 /* any channel */)
&& (!(pfr->channel_id_mask & channel_id_bit)))
&& (!(pfr->channel_id_mask & get_channel_id_bit_mask(channel_id))))
return(0); /* Wrong channel */

if(real_skb)
Expand Down Expand Up @@ -3756,6 +3764,23 @@ u_int32_t default_rehash_rss_func(struct sk_buff *skb, struct pfring_pkthdr *hdr

/* ********************************** */

void set_ring_num_channels(struct pf_ring_socket *pfr, u_int32_t num_rx_channels) {
u_int32_t n = num_rx_channels;

if (n > MAX_NUM_RX_CHANNELS) {
n = MAX_NUM_RX_CHANNELS;
if (pfr->num_rx_channels != n) { /* print on first update only */
printk("[PF_RING] Detected number of channels (%d) is too big, max %d supported",
num_rx_channels, MAX_NUM_RX_CHANNELS);
}
}

if (pfr->num_rx_channels != n)
pfr->num_rx_channels = n;
}

/* ********************************** */

/*
* Add the specified skb to the ring so that userland apps
* can use the packet.
Expand Down Expand Up @@ -3789,8 +3814,8 @@ static int add_skb_to_ring(struct sk_buff *skb,
if((!pfring_enabled) || ((!pfr->ring_active) && (pfr->master_ring == NULL)))
return(-1);

if(pfr->num_rx_channels != num_rx_channels) /* Constantly updated */
pfr->num_rx_channels = num_rx_channels;
set_ring_num_channels(pfr, num_rx_channels); /* Constantly updated */

hdr->extended_hdr.parsed_pkt.last_matched_rule_id = (u_int16_t)-1;

atomic_inc(&pfr->num_ring_users);
Expand Down Expand Up @@ -5415,8 +5440,7 @@ static int ring_release(struct socket *sock)
int i;
/* Reset quick mode for all channels */
for(i=0; i<MAX_NUM_RX_CHANNELS; i++) {
u_int64_t channel_id_bit = (u_int64_t) 1 << i;
if((pfr->channel_id_mask & channel_id_bit) && netns->quick_mode_rings[dev_index][i] == pfr)
if((pfr->channel_id_mask & get_channel_id_bit_mask(i)) && netns->quick_mode_rings[dev_index][i] == pfr)
netns->quick_mode_rings[dev_index][i] = NULL;
}
}
Expand Down Expand Up @@ -5594,7 +5618,7 @@ static int packet_ring_bind(struct sock *sk, pf_ring_device *dev)

pfr->last_bind_dev = dev;

pfr->num_rx_channels = get_num_rx_queues(pfr->ring_dev->dev);
set_ring_num_channels(pfr, get_num_rx_queues(pfr->ring_dev->dev));

if(dev == &any_device_element && !quick_mode) {
netns->num_any_rings++;
Expand Down Expand Up @@ -7127,9 +7151,7 @@ static int ring_setsockopt(struct socket *sock,

if(quick_mode) {
for (i = 0; i < pfr->num_rx_channels; i++) {
u_int64_t channel_id_bit = ((u_int64_t) ((u_int64_t) 1) << i);

if(channel_id_mask & channel_id_bit) {
if(channel_id_mask & get_channel_id_bit_mask(i)) {
if(netns->quick_mode_rings[dev_index][i] != NULL)
return(-EINVAL); /* Socket already bound on this device */
}
Expand All @@ -7138,16 +7160,9 @@ static int ring_setsockopt(struct socket *sock,

/* Everything seems to work thus let's set the values */

if (pfr->num_rx_channels >= MAX_NUM_RX_CHANNELS) {
printk("[PF_RING] Detected number of channels (%d) is too big, max %d supported",
pfr->num_rx_channels, MAX_NUM_RX_CHANNELS);
}

for (i = 0; i < pfr->num_rx_channels; i++) {
if (i < MAX_NUM_RX_CHANNELS) { /* safety check (do not exceed mask size) */
u_int64_t channel_id_bit = ((u_int64_t) ((u_int64_t) 1) << i);

if(channel_id_mask & channel_id_bit) {
if(channel_id_mask & get_channel_id_bit_mask(i)) {
debug_printk(2, "Setting channel %d\n", i);

if(quick_mode) {
Expand Down

0 comments on commit 2939557

Please sign in to comment.