int pfring_dna_open(pfring *ring) { int channel_id = 0; int rc; int i; char *at; ring->direction = rx_only_direction; ring->close = pfring_dna_close; ring->set_sampling_rate = pfring_dna_set_sampling_rate; ring->stats = pfring_dna_stats; ring->recv = pfring_dna_recv; ring->enable_ring = pfring_dna_enable_ring; ring->set_direction = pfring_dna_set_direction; ring->poll = pfring_dna_poll; ring->set_poll_watermark = pfring_mod_set_poll_watermark; ring->set_poll_duration = pfring_mod_set_poll_duration; ring->set_channel_id = pfring_mod_set_channel_id; ring->set_application_name = pfring_mod_set_application_name; ring->set_application_stats = pfring_mod_set_application_stats; ring->get_appl_stats_file_name = pfring_mod_get_appl_stats_file_name; ring->bind = pfring_mod_bind; ring->get_num_rx_channels = pfring_mod_get_num_rx_channels; ring->get_selectable_fd = pfring_mod_get_selectable_fd; ring->set_socket_mode = pfring_mod_set_socket_mode; ring->get_ring_id = pfring_mod_get_ring_id; ring->version = pfring_mod_version; ring->get_bound_device_address = pfring_mod_get_bound_device_address; ring->get_bound_device_ifindex = pfring_mod_get_bound_device_ifindex; ring->get_device_ifindex = pfring_mod_get_device_ifindex; ring->get_slot_header_len = pfring_mod_get_slot_header_len; ring->set_virtual_device = pfring_mod_set_virtual_device; ring->add_hw_rule = pfring_hw_ft_add_hw_rule; ring->remove_hw_rule = pfring_hw_ft_remove_hw_rule; ring->loopback_test = pfring_mod_loopback_test; ring->disable_ring = pfring_mod_disable_ring; ring->handle_hash_filtering_rule = pfring_mod_handle_hash_filtering_rule; ring->add_filtering_rule = pfring_mod_add_filtering_rule; ring->remove_filtering_rule = pfring_mod_remove_filtering_rule; ring->toggle_filtering_policy = pfring_mod_toggle_filtering_policy; ring->shutdown = pfring_mod_shutdown; /* These functions are set by the dna library: (when supported by the device) * ring->send * ring->send_get_time * ring->next_pkt_time * ring->next_pkt_raw_timestamp * ring->set_device_clock * ring->get_device_clock */ ring->poll_duration = DEFAULT_POLL_DURATION; ring->dna.last_dna_operation = remove_device_mapping; ring->fd = socket(PF_RING, SOCK_RAW, htons(ETH_P_ALL)); #ifdef DEBUG printf("Open RING [fd=%d]\n", ring->fd); #endif if(ring->fd < 0) return -1; at = strchr(ring->device_name, '@'); if(at != NULL) { at[0] = '\0'; /* Syntax ethX@1 channel 1 */ channel_id = atoi(&at[1]); } ring->dna.dna_dev.channel_id = channel_id; rc = pfring_map_dna_device(ring, add_device_mapping, ring->device_name); if(rc < 0) { #if 0 printf("pfring_map_dna_device() failed [rc=%d]: device already in use, channel not existing or non-DNA driver?\n", rc); printf("Make sure that you load the DNA-driver *after* you loaded the PF_RING kernel module\n"); #endif return -1; } rc = pfring_get_mapped_dna_device(ring, &ring->dna.dna_dev); if(rc < 0) { printf("pfring_get_mapped_dna_device() failed [rc=%d]\n", rc); pfring_map_dna_device(ring, remove_device_mapping, ring->device_name); close(ring->fd); return -1; } #ifdef DEBUG printf("[num_slots=%d][slot_len=%d][tot_mem_len=%d]\n", ring->dna.dna_dev.packet_memory_num_slots, ring->dna.dna_dev.packet_memory_slot_len, ring->dna.dna_dev.packet_memory_tot_len); printf("[memory_num_slots=%d][memory_slot_len=%d]" "[memory_tot_len=%d]\n", ring->dna.dna_dev.descr_packet_memory_num_slots, ring->dna.dna_dev.descr_packet_memory_slot_len, ring->dna.dna_dev.descr_packet_memory_tot_len); #endif ring->dna.dna_mapped_device = 1; /* ***************************************** */ for(i=0; i<ring->dna.dna_dev.mem_info.rx.packet_memory_num_chunks; i++) { ring->dna.dna_dev.rx_packet_memory[i] = (unsigned long)mmap(NULL, ring->dna.dna_dev.mem_info.rx.packet_memory_chunk_len, PROT_READ|PROT_WRITE, MAP_SHARED, ring->fd, (100+i)*getpagesize()); if(ring->dna.dna_dev.rx_packet_memory[i] == (unsigned long)MAP_FAILED) { printf("mmap(100/%d) failed", i); close(ring->fd); return -1; } } /* ***************************************** */ for(i=0; i<ring->dna.dna_dev.mem_info.tx.packet_memory_num_chunks; i++) { ring->dna.dna_dev.tx_packet_memory[i] = (unsigned long)mmap(NULL, ring->dna.dna_dev.mem_info.tx.packet_memory_chunk_len, PROT_READ|PROT_WRITE, MAP_SHARED, ring->fd, (100+ring->dna.dna_dev.mem_info.rx.packet_memory_num_chunks+i)*getpagesize()); if(ring->dna.dna_dev.tx_packet_memory[i] == (unsigned long)MAP_FAILED) { printf("mmap(100/%d) failed", i); close(ring->fd); return -1; } } /* ***************************************** */ if(ring->dna.dna_dev.mem_info.rx.descr_packet_memory_tot_len > 0) { ring->dna.dna_dev.rx_descr_packet_memory = (void*)mmap(NULL, ring->dna.dna_dev.mem_info.rx.descr_packet_memory_tot_len, PROT_READ|PROT_WRITE, MAP_SHARED, ring->fd, 1*getpagesize()); if(ring->dna.dna_dev.rx_descr_packet_memory == MAP_FAILED) { printf("mmap(1) failed"); close(ring->fd); return -1; } } /* ***************************************** */ if(ring->dna.dna_dev.mem_info.tx.descr_packet_memory_tot_len > 0) { ring->dna.dna_dev.tx_descr_packet_memory = (void*)mmap(NULL, ring->dna.dna_dev.mem_info.tx.descr_packet_memory_tot_len, PROT_READ|PROT_WRITE, MAP_SHARED, ring->fd, 3*getpagesize()); if(ring->dna.dna_dev.tx_descr_packet_memory == MAP_FAILED) { printf("mmap(3) failed"); close(ring->fd); return -1; } } /* ***************************************** */ if(ring->dna.dna_dev.mem_info.phys_card_memory_len > 0) { /* some DNA drivers do not use this memory */ ring->dna.dna_dev.phys_card_memory = (void*)mmap(NULL, ring->dna.dna_dev.mem_info.phys_card_memory_len, PROT_READ|PROT_WRITE, MAP_SHARED, ring->fd, 2*getpagesize()); if(ring->dna.dna_dev.phys_card_memory == MAP_FAILED) { printf("mmap(2) failed"); close(ring->fd); return -1; } } /* ***************************************** */ if(ring->promisc) { if(pfring_set_if_promisc(ring->device_name, 1) == 0) ring->clear_promisc = 1; } /* ***************************************** */ pfring_set_filtering_mode(ring, hardware_only); /* ***************************************** */ rc = dna_init(ring, sizeof(pfring)); if(rc < 0) { printf("dna_init() failed\n"); close(ring->fd); return rc; } pfring_enable_hw_timestamp(ring, ring->device_name, ring->hw_ts.enable_hw_timestamp ? 1 : 0, 0 /* TX timestamp disabled by default */); #ifdef DEBUG pfring_dump_dna_stats(ring); #endif pfring_hw_ft_init(ring); return 0; }
int pfring_mod_open(pfring *ring) { int rc; u_int memSlotsLen; /* Setting pointers, we need these functions soon */ ring->close = pfring_mod_close; ring->stats = pfring_mod_stats; ring->recv = pfring_mod_recv; ring->set_poll_watermark = pfring_mod_set_poll_watermark; ring->set_poll_duration = pfring_mod_set_poll_duration; ring->add_hw_rule = pfring_mod_add_hw_rule; ring->remove_hw_rule = pfring_mod_remove_hw_rule; ring->set_channel_id = pfring_mod_set_channel_id; ring->set_application_name = pfring_mod_set_application_name; ring->bind = pfring_mod_bind; ring->send = pfring_mod_send; ring->get_num_rx_channels = pfring_mod_get_num_rx_channels; ring->set_sampling_rate = pfring_mod_set_sampling_rate; ring->get_selectable_fd = pfring_mod_get_selectable_fd; ring->set_direction = pfring_mod_set_direction; ring->set_cluster = pfring_mod_set_cluster; ring->remove_from_cluster = pfring_mod_remove_from_cluster; ring->set_master_id = pfring_mod_set_master_id; ring->set_master = pfring_mod_set_master; ring->get_ring_id = pfring_mod_get_ring_id; ring->get_num_queued_pkts = pfring_mod_get_num_queued_pkts; ring->get_packet_consumer_mode = pfring_mod_get_packet_consumer_mode; ring->set_packet_consumer_mode = pfring_mod_set_packet_consumer_mode; ring->get_hash_filtering_rule_stats = pfring_mod_get_hash_filtering_rule_stats; ring->handle_hash_filtering_rule = pfring_mod_handle_hash_filtering_rule; ring->purge_idle_hash_rules = pfring_mod_purge_idle_hash_rules; ring->add_filtering_rule = pfring_mod_add_filtering_rule; ring->remove_filtering_rule = pfring_mod_remove_filtering_rule; ring->get_filtering_rule_stats = pfring_mod_get_filtering_rule_stats; ring->toggle_filtering_policy = pfring_mod_toggle_filtering_policy; ring->enable_rss_rehash = pfring_mod_enable_rss_rehash; ring->poll = pfring_mod_poll; ring->version = pfring_mod_version; ring->get_bound_device_address = pfring_mod_get_bound_device_address; ring->get_slot_header_len = pfring_mod_get_slot_header_len; ring->set_virtual_device = pfring_mod_set_virtual_device; ring->loopback_test = pfring_mod_loopback_test; ring->enable_ring = pfring_mod_enable_ring; ring->disable_ring = pfring_mod_disable_ring; ring->is_pkt_available = pfring_mod_is_pkt_available; ring->set_bpf_filter = pfring_mod_set_bpf_filter; ring->poll_duration = DEFAULT_POLL_DURATION; ring->fd = socket(PF_RING, SOCK_RAW, htons(ETH_P_ALL)); if(ring->fd < 0) return -1; #ifdef RING_DEBUG printf("Open RING [fd=%d]\n", ring->fd); #endif if(ring->caplen > MAX_CAPLEN) ring->caplen = MAX_CAPLEN; rc = setsockopt(ring->fd, 0, SO_RING_BUCKET_LEN, &ring->caplen, sizeof(ring->caplen)); if (rc < 0) { close(ring->fd); return -1; } /* printf("channel_id=%d\n", channel_id); */ if(!strcmp(ring->device_name, "none")) { /* No binding yet */ rc = 0; } else /* "any" or "<interface name>" */ rc = pfring_bind(ring, ring->device_name); if(rc < 0) { close(ring->fd); return -1; } ring->kernel_packet_consumer = 0; ring->buffer = (char *)mmap(NULL, PAGE_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, ring->fd, 0); if(ring->buffer == MAP_FAILED) { printf("mmap() failed: try with a smaller snaplen\n"); close(ring->fd); return -1; } ring->slots_info = (FlowSlotInfo *)ring->buffer; if(ring->slots_info->version != RING_FLOWSLOT_VERSION) { printf("Wrong RING version: " "kernel is %i, libpfring was compiled with %i\n", ring->slots_info->version, RING_FLOWSLOT_VERSION); close(ring->fd); return -1; } memSlotsLen = ring->slots_info->tot_mem; munmap(ring->buffer, PAGE_SIZE); ring->buffer = (char *)mmap(NULL, memSlotsLen, PROT_READ|PROT_WRITE, MAP_SHARED, ring->fd, 0); /* printf("mmap len %u\n", memSlotsLen); */ if(ring->buffer == MAP_FAILED) { printf("mmap() failed"); close(ring->fd); return -1; } ring->slots_info = (FlowSlotInfo *)ring->buffer; ring->slots = (char *)(ring->buffer+sizeof(FlowSlotInfo)); #ifdef RING_DEBUG printf("RING (%s): tot_mem=%u/max_slot_len=%u/" "insert_off=%u/remove_off=%u/dropped=%lu\n", ring->device_name, ring->slots_info->tot_mem, ring->slots_info->slot_len, ring->slots_info->insert_off, ring->slots_info->remove_off, ring->slots_info->tot_lost); #endif if(ring->promisc) { if(set_if_promisc(ring->device_name, 1) == 0) ring->clear_promisc = 1; } #ifdef ENABLE_HW_TIMESTAMP pfring_enable_hw_timestamp(ring, ring->device_name); #endif ring->slot_header_len = pfring_get_slot_header_len(ring); if(ring->slot_header_len == (u_int16_t)-1) { printf("ring failure (pfring_get_slot_header_len)\n"); return -1; } return 0; }
int pfring_mod_bind(pfring *ring, char *device_name) { struct sockaddr sa; char *at, *elem, name_copy[256]; u_int32_t channel_mask = RING_ANY_CHANNEL; int rc = 0; if((device_name == NULL) || (strcmp(device_name, "none") == 0)) return(-1); /* FIX: in case of multiple interfaces the channel ID must be the same */ at = strchr(device_name, '@'); if(at != NULL) { char *tok, *pos = NULL; at[0] = '\0'; /* Syntax ethX@1,5 channel 1 and 5 ethX@1-5 channel 1,2...5 ethX@1-3,5-7 channel 1,2,3,5,6,7 */ tok = strtok_r(&at[1], ",", &pos); channel_mask = 0; while(tok != NULL) { char *dash = strchr(tok, '-'); int32_t min_val, max_val, i; if(dash) { dash[0] = '\0'; min_val = atoi(tok); max_val = atoi(&dash[1]); } else min_val = max_val = atoi(tok); for(i = min_val; i <= max_val; i++) channel_mask |= 1 << i; tok = strtok_r(NULL, ",", &pos); } } /* Setup TX */ ring->sock_tx.sll_family = PF_PACKET; ring->sock_tx.sll_protocol = htons(ETH_P_ALL); snprintf(name_copy, sizeof(name_copy), "%s", device_name); elem = strtok(name_copy, ";,"); while(elem != NULL) { memset(&sa, 0, sizeof(sa)); sa.sa_family = PF_RING; snprintf(sa.sa_data, sizeof(sa.sa_data), "%s", elem); rc = bind(ring->fd, (struct sockaddr *)&sa, sizeof(sa)); if(rc == 0) { /* if(channel_mask != RING_ANY_CHANNEL) */ { rc = pfring_set_channel_mask(ring, channel_mask); if(rc != 0) printf("pfring_set_channel_id() failed: %d\n", rc); } } pfring_enable_hw_timestamp(ring, elem, ring->enable_hw_timestamp ? 1 : 0, 0 /* TX timestamp disabled by default */); elem = strtok(NULL, ";,"); } return(rc); }