blob: c64d6773419e0c20ab8acf157acba02e0d7dde86 [file] [log] [blame]
/*
*
* (C) 2005-11 - Luca Deri <deri@ntop.org>
* Alfredo Cardigliano <cardigliano@ntop.org>
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lessed General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
*/
#include "pfring.h"
#include "pfring_utils.h"
#include "pfring_mod.h"
#include "pfring_mod_multi.h"
// #define MULTI_RING_DEBUG
struct ring_list_element {
pfring *ring;
struct ring_list_element *next;
};
int pfring_mod_multi_open(pfring *ring) {
int rc;
char *device_list = ring->device_name;
/* Opening master ring */
ring->device_name = "none";
rc = pfring_mod_open(ring);
ring->device_name = device_list;
if (rc < 0)
return rc;
ring->close = pfring_mod_multi_close;
ring->add_hw_rule = pfring_mod_multi_add_hw_rule;
ring->remove_hw_rule = pfring_mod_multi_remove_hw_rule;
ring->bind = pfring_mod_multi_bind;
ring->set_sampling_rate = pfring_mod_multi_set_sampling_rate;
ring->set_direction = pfring_mod_multi_set_direction;
ring->enable_rss_rehash = pfring_mod_multi_enable_rss_rehash;
//TODO
//? ring->set_virtual_device
//? ring->set_channel_id
//? ring->set_application_name
//? ring->get_num_rx_channels
ring->send = NULL;
ring->set_cluster = NULL;
ring->remove_from_cluster = NULL;
ring->set_master_id = NULL;
ring->set_master = NULL;
ring->priv_data = NULL;
rc = pfring_bind(ring, device_list);
if (rc < 0) {
pfring_mod_multi_close(ring);
return rc;
}
return 0;
}
/* ******************************* */
void pfring_mod_multi_close(pfring *ring) {
pfring_mod_close(ring);
struct ring_list_element *tmp_elem;
struct ring_list_element *elem = (struct ring_list_element *) ring->priv_data;
ring->priv_data = NULL;
while(elem != NULL) {
pfring_close(elem->ring);
tmp_elem = elem;
elem = elem->next;
free(tmp_elem);
}
}
/* ******************************* */
int pfring_mod_multi_bind(pfring *ring, char *device_name) {
char *tok, *pos = NULL;
char dev_name[16];
int rc;
tok = strtok_r(device_name, ";", &pos);
while(tok != NULL){
pfring *new_ring = NULL;
struct ring_list_element *elem;
snprintf(dev_name, sizeof(dev_name), "default:%s", tok);
new_ring = pfring_open(dev_name, ring->promisc, ring->caplen, 0 /* set in master only */);
if (new_ring == NULL)
return -1;
rc = pfring_set_master(new_ring /* slave */, ring /* master */);
if (rc < 0)
return rc;
elem = malloc(sizeof(struct ring_list_element));
if (elem == NULL) {
pfring_close(new_ring);
return -1;
}
elem->ring = new_ring;
elem->next = (struct ring_list_element *) ring->priv_data;
ring->priv_data = (void *) elem;
tok = strtok_r(NULL, ";", &pos);
}
return 0;
}
/* ******************************* */
int pfring_mod_multi_add_hw_rule(pfring *ring, hw_filtering_rule *rule) {
struct ring_list_element *elem = (struct ring_list_element *) ring->priv_data;
while(elem != NULL) {
if (pfring_add_hw_rule(elem->ring, rule) < 0) {
pfring_remove_hw_rule(ring, rule->rule_id);
return -1;
}
elem = elem->next;
}
return 0;
}
/* ******************************* */
int pfring_mod_multi_remove_hw_rule(pfring *ring, u_int16_t rule_id) {
struct ring_list_element *elem = (struct ring_list_element *) ring->priv_data;
while(elem != NULL) {
pfring_remove_hw_rule(elem->ring, rule_id);
elem = elem->next;
}
return 0;
}
/* ******************************* */
int pfring_mod_multi_set_sampling_rate(pfring *ring, u_int32_t rate /* 1 = no sampling */) {
struct ring_list_element *elem = (struct ring_list_element *) ring->priv_data;
while(elem != NULL) {
if(pfring_set_sampling_rate(elem->ring, rate)<0)
return -1;
elem = elem->next;
}
return 0;
}
/* ******************************* */
int pfring_mod_multi_set_direction(pfring *ring, packet_direction direction) {
struct ring_list_element *elem = (struct ring_list_element *) ring->priv_data;
while(elem != NULL) {
if(pfring_set_direction(elem->ring, direction)<0)
return -1;
elem = elem->next;
}
return 0;
}
/* ******************************* */
int pfring_mod_multi_enable_rss_rehash(pfring *ring) {
struct ring_list_element *elem = (struct ring_list_element *) ring->priv_data;
while(elem != NULL) {
if(pfring_enable_rss_rehash(elem->ring)<0)
return -1;
elem = elem->next;
}
return 0;
}